blob: 094e957f324f7be4d2fd75dd22089ce962d5a2aa [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 Vishniakoua7333112023-10-27 13:33:29 -0700366 void setStaleEventTimeout(std::chrono::nanoseconds timeout) { mStaleEventTimeout = timeout; }
367
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800368 void assertUserActivityNotPoked() {
369 std::unique_lock lock(mLock);
370 base::ScopedLockAssertion assumeLocked(mLock);
371
372 std::optional<UserActivityPokeEvent> pokeEvent =
373 getItemFromStorageLockedInterruptible(500ms, mUserActivityPokeEvents, lock,
374 mNotifyUserActivity);
375
376 ASSERT_FALSE(pokeEvent) << "Expected user activity not to have been poked";
Josep del Riob3981622023-04-18 15:49:45 +0000377 }
378
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800379 /**
380 * Asserts that a user activity poke has happened. The earliest recorded poke event will be
381 * cleared after this call.
382 *
383 * If an expected UserActivityPokeEvent is provided, asserts that the given event is the
384 * earliest recorded poke event.
385 */
386 void assertUserActivityPoked(std::optional<UserActivityPokeEvent> expectedPokeEvent = {}) {
387 std::unique_lock lock(mLock);
388 base::ScopedLockAssertion assumeLocked(mLock);
389
390 std::optional<UserActivityPokeEvent> pokeEvent =
391 getItemFromStorageLockedInterruptible(500ms, mUserActivityPokeEvents, lock,
392 mNotifyUserActivity);
393 ASSERT_TRUE(pokeEvent) << "Expected a user poke event";
394
395 if (expectedPokeEvent) {
396 ASSERT_EQ(expectedPokeEvent, *pokeEvent);
397 }
Josep del Riob3981622023-04-18 15:49:45 +0000398 }
399
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000400 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000401 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
402 }
403
404 void assertNotifyDeviceInteractionWasNotCalled() {
405 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
406 }
407
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000408 void setUnhandledKeyHandler(std::function<std::optional<KeyEvent>(const KeyEvent&)> handler) {
409 std::scoped_lock lock(mLock);
410 mUnhandledKeyHandler = handler;
411 }
412
413 void assertUnhandledKeyReported(int32_t keycode) {
414 std::unique_lock lock(mLock);
415 base::ScopedLockAssertion assumeLocked(mLock);
416 std::optional<int32_t> unhandledKeycode =
417 getItemFromStorageLockedInterruptible(100ms, mReportedUnhandledKeycodes, lock,
418 mNotifyUnhandledKey);
419 ASSERT_TRUE(unhandledKeycode) << "Expected unhandled key to be reported";
420 ASSERT_EQ(unhandledKeycode, keycode);
421 }
422
423 void assertUnhandledKeyNotReported() {
424 std::unique_lock lock(mLock);
425 base::ScopedLockAssertion assumeLocked(mLock);
426 std::optional<int32_t> unhandledKeycode =
427 getItemFromStorageLockedInterruptible(10ms, mReportedUnhandledKeycodes, lock,
428 mNotifyUnhandledKey);
429 ASSERT_FALSE(unhandledKeycode) << "Expected unhandled key NOT to be reported";
430 }
431
Michael Wrightd02c5b62014-02-10 15:10:22 -0800432private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700433 std::mutex mLock;
434 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
435 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
436 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
437 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800438
Prabir Pradhan99987712020-11-10 18:43:05 -0800439 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000440
441 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800442
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700443 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700444 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800445 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
446 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700447 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800448 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
449 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700450
arthurhungf452d0b2021-01-06 00:19:52 +0800451 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800452 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800453
454 std::condition_variable mNotifyUserActivity;
455 std::queue<UserActivityPokeEvent> mUserActivityPokeEvents;
arthurhungf452d0b2021-01-06 00:19:52 +0800456
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800457 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
458
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700459 std::chrono::nanoseconds mStaleEventTimeout = 1000ms;
460
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000461 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000462
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000463 std::condition_variable mNotifyUnhandledKey;
464 std::queue<int32_t> mReportedUnhandledKeycodes GUARDED_BY(mLock);
465 std::function<std::optional<KeyEvent>(const KeyEvent&)> mUnhandledKeyHandler GUARDED_BY(mLock);
466
Prabir Pradhanedd96402022-02-15 01:46:16 -0800467 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
468 // for a specific container to become non-empty. When the container is non-empty, return the
469 // first entry from the container and erase it.
470 template <class T>
471 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
472 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
473 // If there is an ANR, Dispatcher won't be idle because there are still events
474 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
475 // before checking if ANR was called.
476 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
477 // to provide it some time to act. 100ms seems reasonable.
478 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
479 const std::chrono::time_point start = std::chrono::steady_clock::now();
480 std::optional<T> token =
481 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
482 if (!token.has_value()) {
483 ADD_FAILURE() << "Did not receive the ANR callback";
484 return {};
485 }
486
487 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
488 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
489 // the dispatcher started counting before this function was called
490 if (std::chrono::abs(timeout - waited) > 100ms) {
491 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
492 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
493 << "ms, but waited "
494 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
495 << "ms instead";
496 }
497 return *token;
498 }
499
500 template <class T>
501 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
502 std::queue<T>& storage,
503 std::unique_lock<std::mutex>& lock,
504 std::condition_variable& condition)
505 REQUIRES(mLock) {
506 condition.wait_for(lock, timeout,
507 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
508 if (storage.empty()) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800509 return std::nullopt;
510 }
511 T item = storage.front();
512 storage.pop();
513 return std::make_optional(item);
514 }
515
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600516 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700517 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800518 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800519 }
520
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000521 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800522 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700523 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800524 ASSERT_TRUE(pid.has_value());
525 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700526 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500527 }
528
Prabir Pradhanedd96402022-02-15 01:46:16 -0800529 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000530 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500531 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800532 ASSERT_TRUE(pid.has_value());
533 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500534 mNotifyAnr.notify_all();
535 }
536
537 void notifyNoFocusedWindowAnr(
538 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
539 std::scoped_lock lock(mLock);
540 mAnrApplications.push(applicationHandle);
541 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800542 }
543
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800544 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
545 std::scoped_lock lock(mLock);
546 mBrokenInputChannels.push(connectionToken);
547 mNotifyInputChannelBroken.notify_all();
548 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800549
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600550 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700551
Chris Yef59a2f42020-10-16 12:55:26 -0700552 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
553 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
554 const std::vector<float>& values) override {}
555
556 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
557 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000558
Chris Yefb552902021-02-03 17:18:37 -0800559 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
560
Prabir Pradhana41d2442023-04-20 21:30:40 +0000561 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700562 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000563 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700564 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000565 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
566 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800567 break;
568 }
569
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700570 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000571 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
572 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800573 break;
574 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700575 default: {
576 ADD_FAILURE() << "Should only filter keys or motions";
577 break;
578 }
Jackal Guof9696682018-10-05 12:23:23 +0800579 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800580 return true;
581 }
582
Prabir Pradhana41d2442023-04-20 21:30:40 +0000583 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
584 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800585 // Clear intercept state when we handled the event.
586 mInterceptKeyTimeout = 0ms;
587 }
588 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800589
Yeabkal Wubshit88a90412023-12-21 18:23:04 -0800590 void interceptMotionBeforeQueueing(int32_t, uint32_t, int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800591
Prabir Pradhana41d2442023-04-20 21:30:40 +0000592 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800593 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
594 // Clear intercept state so we could dispatch the event in next wake.
595 mInterceptKeyTimeout = 0ms;
596 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800597 }
598
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000599 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent& event,
Prabir Pradhana41d2442023-04-20 21:30:40 +0000600 uint32_t) override {
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000601 std::scoped_lock lock(mLock);
602 mReportedUnhandledKeycodes.emplace(event.getKeyCode());
603 mNotifyUnhandledKey.notify_all();
604 return mUnhandledKeyHandler != nullptr ? mUnhandledKeyHandler(event) : std::nullopt;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800605 }
606
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600607 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
608 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700609 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800610 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
611 * essentially a passthrough for notifySwitch.
612 */
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000613 mLastNotifySwitch =
614 NotifySwitchArgs(InputEvent::nextId(), when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800615 }
616
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800617 void pokeUserActivity(nsecs_t eventTime, int32_t eventType, int32_t displayId) override {
Josep del Riob3981622023-04-18 15:49:45 +0000618 std::scoped_lock lock(mLock);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800619 mNotifyUserActivity.notify_all();
620 mUserActivityPokeEvents.push({eventTime, eventType, displayId});
Josep del Riob3981622023-04-18 15:49:45 +0000621 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800622
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700623 bool isStaleEvent(nsecs_t currentTime, nsecs_t eventTime) override {
624 return std::chrono::nanoseconds(currentTime - eventTime) >= mStaleEventTimeout;
625 }
626
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600627 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700628 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700629 mOnPointerDownToken = newToken;
630 }
631
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000632 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800633 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000634 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800635 mPointerCaptureChangedCondition.notify_all();
636 }
637
arthurhungf452d0b2021-01-06 00:19:52 +0800638 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
639 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800640 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800641 mDropTargetWindowToken = token;
642 }
643
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000644 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000645 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000646 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
647 }
648
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700649 void assertFilterInputEventWasCalledInternal(
650 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700651 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800652 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700653 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800654 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800655 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800656};
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700657} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800658
Michael Wrightd02c5b62014-02-10 15:10:22 -0800659// --- InputDispatcherTest ---
660
661class InputDispatcherTest : public testing::Test {
662protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000663 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700664 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800665
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000666 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000667 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700668 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
669
Harry Cutts101ee9b2023-07-06 18:04:14 +0000670 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000671 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700672 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800673 }
674
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000675 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700676 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000677 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700678 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800679 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700680
681 /**
682 * Used for debugging when writing the test
683 */
684 void dumpDispatcherState() {
685 std::string dump;
686 mDispatcher->dump(dump);
687 std::stringstream ss(dump);
688 std::string to;
689
690 while (std::getline(ss, to, '\n')) {
691 ALOGE("%s", to.c_str());
692 }
693 }
Vishnu Nair958da932020-08-21 17:12:37 -0700694
Chavi Weingarten847e8512023-03-29 00:26:09 +0000695 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700696 FocusRequest request;
697 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000698 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700699 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
700 request.displayId = window->getInfo()->displayId;
701 mDispatcher->setFocusedWindow(request);
702 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800703};
704
Michael Wrightd02c5b62014-02-10 15:10:22 -0800705TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
706 KeyEvent event;
707
708 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800709 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
710 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000711 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600712 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800713 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000714 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000715 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800716 << "Should reject key events with undefined action.";
717
718 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800719 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
720 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600721 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800722 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000723 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000724 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800725 << "Should reject key events with ACTION_MULTIPLE.";
726}
727
728TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
729 MotionEvent event;
730 PointerProperties pointerProperties[MAX_POINTERS + 1];
731 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800732 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800733 pointerProperties[i].clear();
734 pointerProperties[i].id = i;
735 pointerCoords[i].clear();
736 }
737
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800738 // Some constants commonly used below
739 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
740 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
741 constexpr int32_t metaState = AMETA_NONE;
742 constexpr MotionClassification classification = MotionClassification::NONE;
743
chaviw9eaa22c2020-07-01 16:21:27 -0700744 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800745 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800746 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000747 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700748 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700749 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
750 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000751 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800752 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000753 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000754 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800755 << "Should reject motion events with undefined action.";
756
757 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800758 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800759 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
760 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
761 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
762 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000763 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800764 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000765 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000766 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800767 << "Should reject motion events with pointer down index too large.";
768
Garfield Tanfbe732e2020-01-24 11:26:14 -0800769 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700770 AMOTION_EVENT_ACTION_POINTER_DOWN |
771 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700772 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
773 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700774 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000775 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800776 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000777 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000778 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800779 << "Should reject motion events with pointer down index too small.";
780
781 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800782 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800783 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
784 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
785 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
786 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000787 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800788 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000789 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000790 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800791 << "Should reject motion events with pointer up index too large.";
792
Garfield Tanfbe732e2020-01-24 11:26:14 -0800793 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700794 AMOTION_EVENT_ACTION_POINTER_UP |
795 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700796 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
797 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700798 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000799 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800800 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000801 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000802 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800803 << "Should reject motion events with pointer up index too small.";
804
805 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800806 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
807 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700808 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700809 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
810 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000811 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800812 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000813 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000814 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800815 << "Should reject motion events with 0 pointers.";
816
Garfield Tanfbe732e2020-01-24 11:26:14 -0800817 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
818 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700819 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700820 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
821 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000822 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800823 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000824 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000825 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800826 << "Should reject motion events with more than MAX_POINTERS pointers.";
827
828 // Rejects motion events with invalid pointer ids.
829 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800830 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
831 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700832 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700833 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
834 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000835 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800836 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000837 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000838 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800839 << "Should reject motion events with pointer ids less than 0.";
840
841 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800842 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
843 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700844 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700845 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
846 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000847 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800848 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000849 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000850 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800851 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
852
853 // Rejects motion events with duplicate pointer ids.
854 pointerProperties[0].id = 1;
855 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800856 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
857 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700858 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700859 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
860 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000861 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800862 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000863 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000864 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800865 << "Should reject motion events with duplicate pointer ids.";
866}
867
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800868/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
869
870TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
871 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000872 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800873 ASSERT_TRUE(mDispatcher->waitForIdle());
874
875 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
876}
877
878TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000879 NotifySwitchArgs args(InputEvent::nextId(), /*eventTime=*/20, /*policyFlags=*/0,
880 /*switchValues=*/1,
Harry Cutts33476232023-01-30 19:57:29 +0000881 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000882 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800883
884 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
885 args.policyFlags |= POLICY_FLAG_TRUSTED;
886 mFakePolicy->assertNotifySwitchWasCalled(args);
887}
888
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700889namespace {
890
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700891static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700892// Default input dispatching timeout if there is no focused application or paused window
893// from which to determine an appropriate dispatching timeout.
894static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
895 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
896 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800897
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800898class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800899public:
Garfield Tan15601662020-09-22 15:32:38 -0700900 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700901 : mConsumer(std::move(clientChannel)), mName(name) {}
chaviwd1c23182019-12-20 18:44:56 -0800902
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800903 std::unique_ptr<InputEvent> consume(std::chrono::milliseconds timeout, bool handled = false) {
904 auto [consumeSeq, event] = receiveEvent(timeout);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700905 if (!consumeSeq) {
906 return nullptr;
907 }
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000908 finishEvent(*consumeSeq, handled);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800909 return std::move(event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700910 }
911
912 /**
913 * Receive an event without acknowledging it.
914 * Return the sequence number that could later be used to send finished signal.
915 */
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800916 std::pair<std::optional<uint32_t>, std::unique_ptr<InputEvent>> receiveEvent(
917 std::chrono::milliseconds timeout) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800918 uint32_t consumeSeq;
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800919 std::unique_ptr<InputEvent> event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800920
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800921 std::chrono::time_point start = std::chrono::steady_clock::now();
922 status_t status = WOULD_BLOCK;
923 while (status == WOULD_BLOCK) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800924 InputEvent* rawEventPtr = nullptr;
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700925 status = mConsumer.consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800926 &rawEventPtr);
927 event = std::unique_ptr<InputEvent>(rawEventPtr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800928 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700929 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800930 break;
931 }
932 }
933
934 if (status == WOULD_BLOCK) {
935 // Just means there's no event available.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800936 return std::make_pair(std::nullopt, nullptr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800937 }
938
939 if (status != OK) {
940 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800941 return std::make_pair(std::nullopt, nullptr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800942 }
943 if (event == nullptr) {
944 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800945 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800946 return std::make_pair(consumeSeq, std::move(event));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700947 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800948
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700949 /**
950 * To be used together with "receiveEvent" to complete the consumption of an event.
951 */
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000952 void finishEvent(uint32_t consumeSeq, bool handled = true) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700953 const status_t status = mConsumer.sendFinishedSignal(consumeSeq, handled);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700954 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800955 }
956
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000957 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700958 const status_t status = mConsumer.sendTimeline(inputEventId, timeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000959 ASSERT_EQ(OK, status);
960 }
961
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700962 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000963 std::optional<int32_t> expectedDisplayId,
964 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800965 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800966
967 ASSERT_NE(nullptr, event) << mName.c_str()
968 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800969 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700970 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
971 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800972
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000973 if (expectedDisplayId.has_value()) {
974 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
975 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800976
Tiger Huang8664f8c2018-10-11 19:14:35 +0800977 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700978 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800979 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700980 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000981 if (expectedFlags.has_value()) {
982 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
983 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800984 break;
985 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700986 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800987 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700988 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000989 if (expectedFlags.has_value()) {
990 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
991 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800992 break;
993 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700994 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100995 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
996 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700997 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800998 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
999 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001000 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001001 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
1002 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001003 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +08001004 FAIL() << "Use 'consumeDragEvent' for DRAG events";
1005 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001006 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001007 }
1008
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001009 std::unique_ptr<MotionEvent> consumeMotion() {
1010 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001011
1012 if (event == nullptr) {
1013 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
1014 return nullptr;
1015 }
1016
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001017 if (event->getType() != InputEventType::MOTION) {
1018 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001019 return nullptr;
1020 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001021 return std::unique_ptr<MotionEvent>(static_cast<MotionEvent*>(event.release()));
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001022 }
1023
1024 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001025 std::unique_ptr<MotionEvent> motionEvent = consumeMotion();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001026 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1027 ASSERT_THAT(*motionEvent, matcher);
1028 }
1029
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001030 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001031 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001032 ASSERT_NE(nullptr, event) << mName.c_str()
1033 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001034 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1035 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001036
1037 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1038 << mName.c_str() << ": event displayId should always be NONE.";
1039
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001040 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1041 EXPECT_EQ(hasFocus, focusEvent.getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001042 }
1043
Prabir Pradhan99987712020-11-10 18:43:05 -08001044 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001045 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -08001046 ASSERT_NE(nullptr, event) << mName.c_str()
1047 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001048 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1049 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001050
1051 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1052 << mName.c_str() << ": event displayId should always be NONE.";
1053
1054 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1055 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1056 }
1057
arthurhungb89ccb02020-12-30 16:19:01 +08001058 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001059 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +08001060 ASSERT_NE(nullptr, event) << mName.c_str()
1061 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001062 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001063
1064 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1065 << mName.c_str() << ": event displayId should always be NONE.";
1066
1067 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1068 EXPECT_EQ(isExiting, dragEvent.isExiting());
1069 EXPECT_EQ(x, dragEvent.getX());
1070 EXPECT_EQ(y, dragEvent.getY());
1071 }
1072
Antonio Kantekf16f2832021-09-28 04:39:20 +00001073 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001074 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +00001075 ASSERT_NE(nullptr, event) << mName.c_str()
1076 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001077 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1078 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001079
1080 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1081 << mName.c_str() << ": event displayId should always be NONE.";
1082 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1083 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1084 }
1085
chaviwd1c23182019-12-20 18:44:56 -08001086 void assertNoEvents() {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001087 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001088 if (event == nullptr) {
1089 return;
1090 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001091 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001092 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001093 ADD_FAILURE() << "Received key event " << keyEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001094 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001095 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001096 ADD_FAILURE() << "Received motion event " << motionEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001097 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001098 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1099 ADD_FAILURE() << "Received focus event, hasFocus = "
1100 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001101 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001102 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1103 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1104 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001105 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001106 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1107 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1108 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001109 }
1110 FAIL() << mName.c_str()
1111 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001112 }
1113
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001114 sp<IBinder> getToken() { return mConsumer.getChannel()->getConnectionToken(); }
chaviwd1c23182019-12-20 18:44:56 -08001115
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001116 int getChannelFd() { return mConsumer.getChannel()->getFd().get(); }
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001117
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001118private:
1119 InputConsumer mConsumer;
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001120 DynamicInputEventFactory mEventFactory;
chaviwd1c23182019-12-20 18:44:56 -08001121
1122 std::string mName;
1123};
1124
chaviw3277faf2021-05-19 16:45:23 -05001125class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001126public:
1127 static const int32_t WIDTH = 600;
1128 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001129
Chris Yea209fde2020-07-22 13:54:51 -07001130 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001131 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001132 int32_t displayId, bool createInputChannel = true)
chaviwd1c23182019-12-20 18:44:56 -08001133 : mName(name) {
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001134 sp<IBinder> token;
1135 if (createInputChannel) {
Garfield Tan15601662020-09-22 15:32:38 -07001136 base::Result<std::unique_ptr<InputChannel>> channel =
1137 dispatcher->createInputChannel(name);
1138 token = (*channel)->getConnectionToken();
1139 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001140 }
1141
1142 inputApplicationHandle->updateInfo();
1143 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1144
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001145 mInfo.token = token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001146 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001147 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001148 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001149 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001150 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001151 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001152 mInfo.globalScaleFactor = 1.0;
1153 mInfo.touchableRegion.clear();
1154 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001155 mInfo.ownerPid = WINDOW_PID;
1156 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001157 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001158 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001159 }
1160
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001161 sp<FakeWindowHandle> clone(int32_t displayId) {
1162 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1163 handle->mInfo = mInfo;
1164 handle->mInfo.displayId = displayId;
1165 handle->mInfo.id = sId++;
1166 handle->mInputReceiver = mInputReceiver;
1167 return handle;
1168 }
1169
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001170 void setTouchable(bool touchable) {
1171 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1172 }
chaviwd1c23182019-12-20 18:44:56 -08001173
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001174 void setFocusable(bool focusable) {
1175 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1176 }
1177
1178 void setVisible(bool visible) {
1179 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1180 }
Vishnu Nair958da932020-08-21 17:12:37 -07001181
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001182 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001183 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001184 }
1185
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001186 void setPaused(bool paused) {
1187 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1188 }
1189
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001190 void setPreventSplitting(bool preventSplitting) {
1191 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001192 }
1193
1194 void setSlippery(bool slippery) {
1195 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1196 }
1197
1198 void setWatchOutsideTouch(bool watchOutside) {
1199 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1200 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001201
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001202 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1203
1204 void setInterceptsStylus(bool interceptsStylus) {
1205 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1206 }
1207
1208 void setDropInput(bool dropInput) {
1209 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1210 }
1211
1212 void setDropInputIfObscured(bool dropInputIfObscured) {
1213 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1214 }
1215
1216 void setNoInputChannel(bool noInputChannel) {
1217 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1218 }
1219
Josep del Riob3981622023-04-18 15:49:45 +00001220 void setDisableUserActivity(bool disableUserActivity) {
1221 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1222 }
1223
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07001224 void setGlobalStylusBlocksTouch(bool shouldGlobalStylusBlockTouch) {
1225 mInfo.setInputConfig(WindowInfo::InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH,
1226 shouldGlobalStylusBlockTouch);
1227 }
1228
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001229 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1230
chaviw3277faf2021-05-19 16:45:23 -05001231 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001232
Bernardo Rufino7393d172021-02-26 13:56:11 +00001233 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1234
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001235 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001236 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001237 mInfo.touchableRegion.clear();
1238 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001239
1240 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1241 ui::Transform translate;
1242 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1243 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001244 }
1245
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001246 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1247
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001248 void setIsWallpaper(bool isWallpaper) {
1249 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1250 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001251
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001252 void setDupTouchToWallpaper(bool hasWallpaper) {
1253 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1254 }
chaviwd1c23182019-12-20 18:44:56 -08001255
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001256 void setTrustedOverlay(bool trustedOverlay) {
1257 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1258 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001259
chaviw9eaa22c2020-07-01 16:21:27 -07001260 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1261 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1262 }
1263
1264 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001265
yunho.shinf4a80b82020-11-16 21:13:57 +09001266 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1267
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001268 std::unique_ptr<KeyEvent> consumeKey(bool handled = true) {
1269 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED, handled);
1270 if (event == nullptr) {
1271 ADD_FAILURE() << "No event";
1272 return nullptr;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001273 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001274 if (event->getType() != InputEventType::KEY) {
1275 ADD_FAILURE() << "Instead of key event, got " << event;
1276 return nullptr;
1277 }
1278 return std::unique_ptr<KeyEvent>(static_cast<KeyEvent*>(event.release()));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001279 }
1280
1281 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001282 std::unique_ptr<KeyEvent> keyEvent = consumeKey();
1283 ASSERT_NE(nullptr, keyEvent);
1284 ASSERT_THAT(*keyEvent, matcher);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001285 }
1286
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001287 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001288 consumeKeyEvent(AllOf(WithKeyAction(ACTION_DOWN), WithDisplayId(expectedDisplayId),
1289 WithFlags(expectedFlags)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001290 }
1291
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001292 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001293 consumeKeyEvent(AllOf(WithKeyAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1294 WithFlags(expectedFlags)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001295 }
1296
Svet Ganov5d3bc372020-01-26 23:11:07 -08001297 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001298 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001299 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1300 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001301 }
1302
1303 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001304 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001305 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1306 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001307 }
1308
1309 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001310 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001311 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1312 }
1313
1314 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1315 std::optional<int32_t> expectedFlags = std::nullopt) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001316 consumeMotionEvent(
1317 AllOf(WithMotionAction(ACTION_DOWN),
1318 testing::Conditional(expectedDisplayId.has_value(),
1319 WithDisplayId(*expectedDisplayId), testing::_),
1320 testing::Conditional(expectedFlags.has_value(), WithFlags(*expectedFlags),
1321 testing::_)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001322 }
1323
Svet Ganov5d3bc372020-01-26 23:11:07 -08001324 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001325 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1326 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001327 const int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001328 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001329 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1330 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001331 }
1332
1333 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001334 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001335 const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001336 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001337 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1338 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001339 }
1340
1341 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001342 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001343 consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1344 WithFlags(expectedFlags)));
Michael Wright3a240c42019-12-10 20:53:41 +00001345 }
1346
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001347 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1348 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001349 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE),
1350 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001351 }
1352
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001353 void consumeMotionOutsideWithZeroedCoords() {
1354 consumeMotionEvent(
1355 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE), WithRawCoords(0, 0)));
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001356 }
1357
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001358 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1359 ASSERT_NE(mInputReceiver, nullptr)
1360 << "Cannot consume events from a window with no receiver";
1361 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1362 }
1363
Prabir Pradhan99987712020-11-10 18:43:05 -08001364 void consumeCaptureEvent(bool hasCapture) {
1365 ASSERT_NE(mInputReceiver, nullptr)
1366 << "Cannot consume events from a window with no receiver";
1367 mInputReceiver->consumeCaptureEvent(hasCapture);
1368 }
1369
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001370 std::unique_ptr<MotionEvent> consumeMotionEvent(
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001371 const ::testing::Matcher<MotionEvent>& matcher = testing::_) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001372 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
1373 if (event == nullptr) {
1374 ADD_FAILURE() << "No event";
1375 return nullptr;
Prabir Pradhan5893d362023-11-17 04:30:40 +00001376 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001377 if (event->getType() != InputEventType::MOTION) {
1378 ADD_FAILURE() << "Instead of motion event, got " << *event;
1379 return nullptr;
1380 }
1381 std::unique_ptr<MotionEvent> motionEvent =
1382 std::unique_ptr<MotionEvent>(static_cast<MotionEvent*>(event.release()));
1383 EXPECT_THAT(*motionEvent, matcher);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001384 return motionEvent;
chaviwd1c23182019-12-20 18:44:56 -08001385 }
1386
arthurhungb89ccb02020-12-30 16:19:01 +08001387 void consumeDragEvent(bool isExiting, float x, float y) {
1388 mInputReceiver->consumeDragEvent(isExiting, x, y);
1389 }
1390
Antonio Kantekf16f2832021-09-28 04:39:20 +00001391 void consumeTouchModeEvent(bool inTouchMode) {
1392 ASSERT_NE(mInputReceiver, nullptr)
1393 << "Cannot consume events from a window with no receiver";
1394 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1395 }
1396
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001397 std::pair<std::optional<uint32_t>, std::unique_ptr<InputEvent>> receiveEvent() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001398 if (mInputReceiver == nullptr) {
1399 ADD_FAILURE() << "Invalid receive event on window with no receiver";
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001400 return std::make_pair(std::nullopt, nullptr);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001401 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001402 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001403 }
1404
1405 void finishEvent(uint32_t sequenceNum) {
1406 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1407 mInputReceiver->finishEvent(sequenceNum);
1408 }
1409
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001410 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1411 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1412 mInputReceiver->sendTimeline(inputEventId, timeline);
1413 }
1414
Arthur Hungb92218b2018-08-14 12:00:21 +08001415 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001416 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001417 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001418 return; // Can't receive events if the window does not have input channel
1419 }
1420 ASSERT_NE(nullptr, mInputReceiver)
1421 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001422 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001423 }
1424
chaviwaf87b3e2019-10-01 16:59:28 -07001425 sp<IBinder> getToken() { return mInfo.token; }
1426
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001427 const std::string& getName() { return mName; }
1428
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001429 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001430 mInfo.ownerPid = ownerPid;
1431 mInfo.ownerUid = ownerUid;
1432 }
1433
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001434 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001435
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001436 void destroyReceiver() { mInputReceiver = nullptr; }
1437
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001438 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1439
chaviwd1c23182019-12-20 18:44:56 -08001440private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001441 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001442 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001443 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001444 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001445 friend class sp<FakeWindowHandle>;
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001446
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001447 std::unique_ptr<InputEvent> consume(std::chrono::milliseconds timeout, bool handled = true) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001448 if (mInputReceiver == nullptr) {
1449 LOG(FATAL) << "Cannot consume event from a window with no input event receiver";
1450 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001451 std::unique_ptr<InputEvent> event = mInputReceiver->consume(timeout, handled);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001452 if (event == nullptr) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001453 ADD_FAILURE() << "Consume failed: no event";
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001454 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001455 return event;
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001456 }
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001457};
1458
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001459std::atomic<int32_t> FakeWindowHandle::sId{1};
1460
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001461class FakeMonitorReceiver {
1462public:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001463 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId)
1464 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001465
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001466 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001467
1468 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001469 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1470 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001471 }
1472
1473 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001474 const auto [sequenceNum, _] = mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1475 return sequenceNum;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001476 }
1477
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001478 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001479
1480 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001481 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1482 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001483 }
1484
1485 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001486 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1487 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001488 }
1489
1490 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001491 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1492 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001493 }
1494
1495 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001496 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001497 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1498 WithDisplayId(expectedDisplayId),
1499 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1500 }
1501
1502 void consumeMotionPointerDown(int32_t pointerIdx) {
1503 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1504 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001505 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1506 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001507 }
1508
1509 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001510 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001511 }
1512
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001513 std::unique_ptr<MotionEvent> consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001514
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001515 void assertNoEvents() { mInputReceiver.assertNoEvents(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001516
1517private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001518 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001519};
1520
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001521static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001522 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001523 int32_t displayId = ADISPLAY_ID_NONE,
1524 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001525 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001526 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001527 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001528 KeyEvent event;
1529 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1530
1531 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001532 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001533 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1534 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001535
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001536 if (!allowKeyRepeat) {
1537 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1538 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001539 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001540 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001541}
1542
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001543static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1544 InputEventInjectionResult result =
1545 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1546 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1547 if (result != InputEventInjectionResult::TIMED_OUT) {
1548 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1549 }
1550}
1551
1552static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001553 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001554 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001555}
1556
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001557// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1558// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1559// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001560static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1561 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001562 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001563 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001564 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001565}
1566
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001567static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001568 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001569 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001570}
1571
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001572static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001573 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001574 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001575 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001576 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001577 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1578 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001579}
1580
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001581static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001582 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1583 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001584 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001585 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1586 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001587 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001588 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001589 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001590 MotionEventBuilder motionBuilder =
1591 MotionEventBuilder(action, source)
1592 .displayId(displayId)
1593 .eventTime(eventTime)
1594 .rawXCursorPosition(cursorPosition.x)
1595 .rawYCursorPosition(cursorPosition.y)
1596 .pointer(
1597 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1598 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1599 motionBuilder.downTime(eventTime);
1600 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001601
1602 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001603 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1604 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001605}
1606
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001607static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1608 int32_t displayId,
1609 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001610 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001611}
1612
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001613static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1614 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001615 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001616 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001617}
1618
Jackal Guof9696682018-10-05 12:23:23 +08001619static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1620 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1621 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001622 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1623 AINPUT_SOURCE_KEYBOARD, displayId, POLICY_FLAG_PASS_TO_USER, action,
1624 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001625
1626 return args;
1627}
1628
Josep del Riob3981622023-04-18 15:49:45 +00001629static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1630 int32_t displayId = ADISPLAY_ID_NONE) {
1631 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1632 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001633 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1634 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C,
1635 AMETA_META_ON, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001636
1637 return args;
1638}
1639
1640static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1641 int32_t displayId = ADISPLAY_ID_NONE) {
1642 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1643 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001644 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1645 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST,
1646 KEY_ASSISTANT, AMETA_NONE, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001647
1648 return args;
1649}
1650
Prabir Pradhan678438e2023-04-13 19:32:51 +00001651[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1652 int32_t displayId,
1653 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001654 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001655 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1656 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1657 }
1658
chaviwd1c23182019-12-20 18:44:56 -08001659 PointerProperties pointerProperties[pointerCount];
1660 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001661
chaviwd1c23182019-12-20 18:44:56 -08001662 for (size_t i = 0; i < pointerCount; i++) {
1663 pointerProperties[i].clear();
1664 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001665 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001666
chaviwd1c23182019-12-20 18:44:56 -08001667 pointerCoords[i].clear();
1668 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1669 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1670 }
Jackal Guof9696682018-10-05 12:23:23 +08001671
1672 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1673 // Define a valid motion event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001674 NotifyMotionArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, source,
1675 displayId, POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0,
1676 /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001677 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001678 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001679 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001680 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001681
1682 return args;
1683}
1684
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001685static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1686 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1687}
1688
chaviwd1c23182019-12-20 18:44:56 -08001689static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1690 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1691}
1692
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001693static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1694 const PointerCaptureRequest& request) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001695 return NotifyPointerCaptureChangedArgs(InputEvent::nextId(), systemTime(SYSTEM_TIME_MONOTONIC),
1696 request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001697}
1698
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001699} // namespace
1700
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001701/**
1702 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1703 * broken channel.
1704 */
1705TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1706 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1707 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001708 sp<FakeWindowHandle>::make(application, mDispatcher,
1709 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001710
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001711 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001712
1713 // Window closes its channel, but the window remains.
1714 window->destroyReceiver();
1715 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1716}
1717
Arthur Hungb92218b2018-08-14 12:00:21 +08001718TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001719 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001720 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1721 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001722
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001723 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001724 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001725 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001726 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001727
1728 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001729 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001730}
1731
Siarhei Vishniakouaeed0da2024-01-09 08:57:13 -08001732using InputDispatcherDeathTest = InputDispatcherTest;
1733
1734/**
1735 * When 'onWindowInfosChanged' arguments contain a duplicate entry for the same window, dispatcher
1736 * should crash.
1737 */
1738TEST_F(InputDispatcherDeathTest, DuplicateWindowInfosAbortDispatcher) {
1739 testing::GTEST_FLAG(death_test_style) = "threadsafe";
1740 ScopedSilentDeath _silentDeath;
1741
1742 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1743 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1744 "Fake Window", ADISPLAY_ID_DEFAULT);
1745 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
1746 {{*window->getInfo(), *window->getInfo()}, {}, 0, 0}),
1747 "Incorrect WindowInfosUpdate provided");
1748}
1749
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001750TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1751 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001752 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1753 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001754
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001755 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001756 // Inject a MotionEvent to an unknown display.
1757 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001758 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001759 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1760
1761 // Window should receive motion event.
1762 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1763}
1764
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001765/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001766 * Calling onWindowInfosChanged once should not cause any issues.
1767 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001768 * called twice.
1769 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001770TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001771 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001772 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1773 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001774 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001775
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001776 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001777 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001778 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001779 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001780 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001781
1782 // Window should receive motion event.
1783 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1784}
1785
1786/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001787 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001788 */
1789TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001790 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001791 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1792 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001793 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001794
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001795 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1796 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001797 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001798 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001799 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001800 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001801
1802 // Window should receive motion event.
1803 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1804}
1805
Arthur Hungb92218b2018-08-14 12:00:21 +08001806// The foreground window should receive the first touch down event.
1807TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001808 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001809 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001810 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001811 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001812 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001813
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001814 mDispatcher->onWindowInfosChanged(
1815 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001816 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001817 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001818 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001819
1820 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001821 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001822 windowSecond->assertNoEvents();
1823}
1824
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001825/**
1826 * Two windows: A top window, and a wallpaper behind the window.
1827 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1828 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001829 * 1. foregroundWindow <-- dup touch to wallpaper
1830 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001831 */
1832TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1833 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1834 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001835 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001836 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001837 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001838 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001839 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001840
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001841 mDispatcher->onWindowInfosChanged(
1842 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001843 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001844 injectMotionEvent(*mDispatcher,
1845 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1846 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
1847 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001848 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1849
1850 // Both foreground window and its wallpaper should receive the touch down
1851 foregroundWindow->consumeMotionDown();
1852 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1853
1854 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001855 injectMotionEvent(*mDispatcher,
1856 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1857 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
1858 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001859 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1860
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001861 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001862 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1863
1864 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001865 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001866 foregroundWindow->consumeMotionCancel();
1867 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1868 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1869}
1870
1871/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001872 * Two fingers down on the window, and lift off the first finger.
1873 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1874 * contains a single pointer.
1875 */
1876TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1877 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1878 sp<FakeWindowHandle> window =
1879 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1880
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001881 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001882 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001883 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1884 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1885 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001886 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001887 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1888 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1889 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1890 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001891 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001892 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1893 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1894 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1895 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001896 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1897 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1898 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1899
1900 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001901 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001902 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1903 window->consumeMotionEvent(
1904 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1905}
1906
1907/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001908 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1909 * with the following differences:
1910 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1911 * clean up the connection.
1912 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1913 * Ensure that there's no crash in the dispatcher.
1914 */
1915TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1916 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1917 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001918 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001919 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001920 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001921 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001922 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001923
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001924 mDispatcher->onWindowInfosChanged(
1925 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001926 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001927 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001928 {100, 200}))
1929 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1930
1931 // Both foreground window and its wallpaper should receive the touch down
1932 foregroundWindow->consumeMotionDown();
1933 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1934
1935 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001936 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001937 ADISPLAY_ID_DEFAULT, {110, 200}))
1938 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1939
1940 foregroundWindow->consumeMotionMove();
1941 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1942
1943 // Wallpaper closes its channel, but the window remains.
1944 wallpaperWindow->destroyReceiver();
1945 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1946
1947 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1948 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001949 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001950 foregroundWindow->consumeMotionCancel();
1951}
1952
Arthur Hungc539dbb2022-12-08 07:45:36 +00001953class ShouldSplitTouchFixture : public InputDispatcherTest,
1954 public ::testing::WithParamInterface<bool> {};
1955INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1956 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001957/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001958 * A single window that receives touch (on top), and a wallpaper window underneath it.
1959 * The top window gets a multitouch gesture.
1960 * Ensure that wallpaper gets the same gesture.
1961 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001962TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001963 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001964 sp<FakeWindowHandle> foregroundWindow =
1965 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1966 foregroundWindow->setDupTouchToWallpaper(true);
1967 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001968
1969 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001970 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001971 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001972
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001973 mDispatcher->onWindowInfosChanged(
1974 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001975
1976 // Touch down on top window
1977 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001978 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001979 {100, 100}))
1980 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1981
1982 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001983 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001984 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1985
1986 // Second finger down on the top window
1987 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001988 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001989 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001990 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1991 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001992 .build();
1993 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001994 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001995 InputEventInjectionSync::WAIT_FOR_RESULT))
1996 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1997
Harry Cutts33476232023-01-30 19:57:29 +00001998 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1999 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002000 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00002001
2002 const MotionEvent secondFingerUpEvent =
2003 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2004 .displayId(ADISPLAY_ID_DEFAULT)
2005 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002006 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2007 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002008 .build();
2009 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002010 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002011 InputEventInjectionSync::WAIT_FOR_RESULT))
2012 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2013 foregroundWindow->consumeMotionPointerUp(0);
2014 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2015
2016 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002017 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002018 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2019 AINPUT_SOURCE_TOUCHSCREEN)
2020 .displayId(ADISPLAY_ID_DEFAULT)
2021 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00002022 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002023 .x(100)
2024 .y(100))
2025 .build(),
2026 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002027 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2028 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2029 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002030}
2031
2032/**
2033 * Two windows: a window on the left and window on the right.
2034 * A third window, wallpaper, is behind both windows, and spans both top windows.
2035 * The first touch down goes to the left window. A second pointer touches down on the right window.
2036 * The touch is split, so both left and right windows should receive ACTION_DOWN.
2037 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
2038 * ACTION_POINTER_DOWN(1).
2039 */
2040TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
2041 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2042 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002043 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002044 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002045 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002046
2047 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002048 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002049 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002050 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002051
2052 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002053 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002054 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002055 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002056
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002057 mDispatcher->onWindowInfosChanged(
2058 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2059 {},
2060 0,
2061 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002062
2063 // Touch down on left window
2064 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002065 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002066 {100, 100}))
2067 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2068
2069 // Both foreground window and its wallpaper should receive the touch down
2070 leftWindow->consumeMotionDown();
2071 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2072
2073 // Second finger down on the right window
2074 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002075 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002076 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002077 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2078 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002079 .build();
2080 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002081 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002082 InputEventInjectionSync::WAIT_FOR_RESULT))
2083 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2084
2085 leftWindow->consumeMotionMove();
2086 // Since the touch is split, right window gets ACTION_DOWN
2087 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002088 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002089 expectedWallpaperFlags);
2090
2091 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002092 mDispatcher->onWindowInfosChanged(
2093 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002094 leftWindow->consumeMotionCancel();
2095 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2096 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2097
2098 // The pointer that's still down on the right window moves, and goes to the right window only.
2099 // As far as the dispatcher's concerned though, both pointers are still present.
2100 const MotionEvent secondFingerMoveEvent =
2101 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2102 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002103 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2104 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002105 .build();
2106 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002107 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002108 InputEventInjectionSync::WAIT_FOR_RESULT));
2109 rightWindow->consumeMotionMove();
2110
2111 leftWindow->assertNoEvents();
2112 rightWindow->assertNoEvents();
2113 wallpaperWindow->assertNoEvents();
2114}
2115
Arthur Hungc539dbb2022-12-08 07:45:36 +00002116/**
2117 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2118 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2119 * The right window should receive ACTION_DOWN.
2120 */
2121TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002122 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002123 sp<FakeWindowHandle> leftWindow =
2124 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2125 leftWindow->setFrame(Rect(0, 0, 200, 200));
2126 leftWindow->setDupTouchToWallpaper(true);
2127 leftWindow->setSlippery(true);
2128
2129 sp<FakeWindowHandle> rightWindow =
2130 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2131 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002132
2133 sp<FakeWindowHandle> wallpaperWindow =
2134 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2135 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002136
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002137 mDispatcher->onWindowInfosChanged(
2138 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2139 {},
2140 0,
2141 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002142
Arthur Hungc539dbb2022-12-08 07:45:36 +00002143 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002144 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002145 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002146 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002147 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002148
2149 // Both foreground window and its wallpaper should receive the touch down
2150 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002151 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2152
Arthur Hungc539dbb2022-12-08 07:45:36 +00002153 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002154 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002155 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002156 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002157 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2158
Arthur Hungc539dbb2022-12-08 07:45:36 +00002159 leftWindow->consumeMotionCancel();
2160 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2161 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002162}
2163
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002164/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002165 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2166 * interactive, it might stop sending this flag.
2167 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2168 * to have a consistent input stream.
2169 *
2170 * Test procedure:
2171 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2172 * DOWN (new gesture).
2173 *
2174 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2175 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2176 *
2177 * We technically just need a single window here, but we are using two windows (spy on top and a
2178 * regular window below) to emulate the actual situation where it happens on the device.
2179 */
2180TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2181 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2182 sp<FakeWindowHandle> spyWindow =
2183 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2184 spyWindow->setFrame(Rect(0, 0, 200, 200));
2185 spyWindow->setTrustedOverlay(true);
2186 spyWindow->setSpy(true);
2187
2188 sp<FakeWindowHandle> window =
2189 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2190 window->setFrame(Rect(0, 0, 200, 200));
2191
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002192 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002193 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002194
2195 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002196 mDispatcher->notifyMotion(
2197 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2198 .deviceId(touchDeviceId)
2199 .policyFlags(DEFAULT_POLICY_FLAGS)
2200 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2201 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002202
Prabir Pradhan678438e2023-04-13 19:32:51 +00002203 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2204 .deviceId(touchDeviceId)
2205 .policyFlags(DEFAULT_POLICY_FLAGS)
2206 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2207 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2208 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002209 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2210 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2211 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2212 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2213
2214 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002215 mDispatcher->notifyMotion(
2216 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2217 .deviceId(touchDeviceId)
2218 .policyFlags(0)
2219 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2220 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2221 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002222 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2223 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2224
2225 // We don't need to reset the device to reproduce the issue, but the reset event typically
2226 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002227 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002228
2229 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002230 mDispatcher->notifyMotion(
2231 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2232 .deviceId(touchDeviceId)
2233 .policyFlags(DEFAULT_POLICY_FLAGS)
2234 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2235 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002236 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2237 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2238
2239 // No more events
2240 spyWindow->assertNoEvents();
2241 window->assertNoEvents();
2242}
2243
2244/**
Linnan Li907ae732023-09-05 17:14:21 +08002245 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
2246 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2247 * interactive, it might stop sending this flag.
2248 * We've already ensured the consistency of the touch event in this case, and we should also ensure
2249 * the consistency of the hover event in this case.
2250 *
2251 * Test procedure:
2252 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
2253 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
2254 *
2255 * We expect to receive two full streams of hover events.
2256 */
2257TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
2258 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2259
2260 sp<FakeWindowHandle> window =
2261 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2262 window->setFrame(Rect(0, 0, 300, 300));
2263
2264 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2265
2266 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2267 .policyFlags(DEFAULT_POLICY_FLAGS)
2268 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2269 .build());
2270 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2271
2272 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2273 .policyFlags(DEFAULT_POLICY_FLAGS)
2274 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2275 .build());
2276 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2277
2278 // Send hover exit without the default policy flags.
2279 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2280 .policyFlags(0)
2281 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2282 .build());
2283
2284 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2285
2286 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
2287 // right event.
2288 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2289 .policyFlags(DEFAULT_POLICY_FLAGS)
2290 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
2291 .build());
2292 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2293
2294 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2295 .policyFlags(DEFAULT_POLICY_FLAGS)
2296 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2297 .build());
2298 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2299
2300 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2301 .policyFlags(DEFAULT_POLICY_FLAGS)
2302 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2303 .build());
2304 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2305}
2306
2307/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002308 * Two windows: a window on the left and a window on the right.
2309 * Mouse is hovered from the right window into the left window.
2310 * Next, we tap on the left window, where the cursor was last seen.
2311 * The second tap is done onto the right window.
2312 * The mouse and tap are from two different devices.
2313 * We technically don't need to set the downtime / eventtime for these events, but setting these
2314 * explicitly helps during debugging.
2315 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2316 * In the buggy implementation, a tap on the right window would cause a crash.
2317 */
2318TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2319 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2320 sp<FakeWindowHandle> leftWindow =
2321 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2322 leftWindow->setFrame(Rect(0, 0, 200, 200));
2323
2324 sp<FakeWindowHandle> rightWindow =
2325 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2326 rightWindow->setFrame(Rect(200, 0, 400, 200));
2327
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002328 mDispatcher->onWindowInfosChanged(
2329 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002330 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2331 // stale.
2332 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2333 const int32_t mouseDeviceId = 6;
2334 const int32_t touchDeviceId = 4;
2335 // Move the cursor from right
2336 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002337 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002338 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2339 AINPUT_SOURCE_MOUSE)
2340 .deviceId(mouseDeviceId)
2341 .downTime(baseTime + 10)
2342 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002343 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002344 .build()));
2345 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2346
2347 // .. to the left window
2348 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002349 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002350 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2351 AINPUT_SOURCE_MOUSE)
2352 .deviceId(mouseDeviceId)
2353 .downTime(baseTime + 10)
2354 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002355 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002356 .build()));
2357 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2358 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2359 // Now tap the left window
2360 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002361 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002362 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2363 AINPUT_SOURCE_TOUCHSCREEN)
2364 .deviceId(touchDeviceId)
2365 .downTime(baseTime + 40)
2366 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002367 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002368 .build()));
2369 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2370 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2371
2372 // release tap
2373 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002374 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002375 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2376 AINPUT_SOURCE_TOUCHSCREEN)
2377 .deviceId(touchDeviceId)
2378 .downTime(baseTime + 40)
2379 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002380 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002381 .build()));
2382 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2383
2384 // Tap the window on the right
2385 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002386 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002387 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2388 AINPUT_SOURCE_TOUCHSCREEN)
2389 .deviceId(touchDeviceId)
2390 .downTime(baseTime + 60)
2391 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002392 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002393 .build()));
2394 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2395
2396 // release tap
2397 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002398 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002399 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2400 AINPUT_SOURCE_TOUCHSCREEN)
2401 .deviceId(touchDeviceId)
2402 .downTime(baseTime + 60)
2403 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002404 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002405 .build()));
2406 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2407
2408 // No more events
2409 leftWindow->assertNoEvents();
2410 rightWindow->assertNoEvents();
2411}
2412
2413/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002414 * Start hovering in a window. While this hover is still active, make another window appear on top.
2415 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2416 * While the top window is present, the hovering is stopped.
2417 * Later, hovering gets resumed again.
2418 * Ensure that new hover gesture is handled correctly.
2419 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2420 * to the window that's currently being hovered over.
2421 */
2422TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2423 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2424 sp<FakeWindowHandle> window =
2425 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2426 window->setFrame(Rect(0, 0, 200, 200));
2427
2428 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002429 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002430
2431 // Start hovering in the window
2432 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2433 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2434 .build());
2435 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2436
2437 // Now, an obscuring window appears!
2438 sp<FakeWindowHandle> obscuringWindow =
2439 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2440 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002441 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002442 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2443 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2444 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2445 obscuringWindow->setNoInputChannel(true);
2446 obscuringWindow->setFocusable(false);
2447 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002448 mDispatcher->onWindowInfosChanged(
2449 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002450
2451 // While this new obscuring window is present, the hovering is stopped
2452 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2453 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2454 .build());
2455 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2456
2457 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002458 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002459
2460 // And a new hover gesture starts.
2461 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2462 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2463 .build());
2464 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2465}
2466
2467/**
2468 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2469 * the obscuring window.
2470 */
2471TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2472 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2473 sp<FakeWindowHandle> window =
2474 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2475 window->setFrame(Rect(0, 0, 200, 200));
2476
2477 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002478 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002479
2480 // Start hovering in the window
2481 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2482 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2483 .build());
2484 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2485
2486 // Now, an obscuring window appears!
2487 sp<FakeWindowHandle> obscuringWindow =
2488 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2489 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002490 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002491 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2492 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2493 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2494 obscuringWindow->setNoInputChannel(true);
2495 obscuringWindow->setFocusable(false);
2496 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002497 mDispatcher->onWindowInfosChanged(
2498 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002499
2500 // While this new obscuring window is present, the hovering continues. The event can't go to the
2501 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2502 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2503 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2504 .build());
2505 obscuringWindow->assertNoEvents();
2506 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2507
2508 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002509 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002510
2511 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2512 // so it should generate a HOVER_ENTER
2513 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2514 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2515 .build());
2516 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2517
2518 // Now the MOVE should be getting dispatched normally
2519 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2520 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2521 .build());
2522 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2523}
2524
2525/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002526 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2527 * events are delivered to the window.
2528 */
2529TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2530 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2531 sp<FakeWindowHandle> window =
2532 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2533 window->setFrame(Rect(0, 0, 200, 200));
2534 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2535
2536 // Start hovering in the window
2537 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2538 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2539 .build());
2540 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2541
2542 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2543 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2544 .build());
2545 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2546
2547 // Scroll with the mouse
2548 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2549 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2550 .build());
2551 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2552}
2553
2554using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2555
2556/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002557 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2558 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002559 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002560TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002561 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2562 sp<FakeWindowHandle> window =
2563 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2564 window->setFrame(Rect(0, 0, 200, 200));
2565
2566 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2567
2568 constexpr int32_t touchDeviceId = 4;
2569 constexpr int32_t stylusDeviceId = 2;
2570
2571 // Stylus down
2572 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2573 .deviceId(stylusDeviceId)
2574 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2575 .build());
2576 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2577
2578 // Touch down
2579 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2580 .deviceId(touchDeviceId)
2581 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2582 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002583
2584 // Touch move
2585 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2586 .deviceId(touchDeviceId)
2587 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2588 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002589 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002590
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002591 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002592 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2593 .deviceId(stylusDeviceId)
2594 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2595 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002596 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2597 WithCoords(101, 111)));
2598
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002599 window->assertNoEvents();
2600}
2601
2602/**
2603 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002604 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002605 * Similar test as above, but with added SPY window.
2606 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002607TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002608 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2609 sp<FakeWindowHandle> window =
2610 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2611 sp<FakeWindowHandle> spyWindow =
2612 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2613 spyWindow->setFrame(Rect(0, 0, 200, 200));
2614 spyWindow->setTrustedOverlay(true);
2615 spyWindow->setSpy(true);
2616 window->setFrame(Rect(0, 0, 200, 200));
2617
2618 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2619
2620 constexpr int32_t touchDeviceId = 4;
2621 constexpr int32_t stylusDeviceId = 2;
2622
2623 // Stylus down
2624 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2625 .deviceId(stylusDeviceId)
2626 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2627 .build());
2628 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2629 spyWindow->consumeMotionEvent(
2630 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2631
2632 // Touch down
2633 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2634 .deviceId(touchDeviceId)
2635 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2636 .build());
2637
2638 // Touch move
2639 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2640 .deviceId(touchDeviceId)
2641 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2642 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002643
2644 // Touch is ignored because stylus is already down
2645
2646 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002647 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2648 .deviceId(stylusDeviceId)
2649 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2650 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002651 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2652 WithCoords(101, 111)));
2653 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2654 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002655
2656 window->assertNoEvents();
2657 spyWindow->assertNoEvents();
2658}
2659
2660/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002661 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002662 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002663 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002664TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002665 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2666 sp<FakeWindowHandle> window =
2667 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2668 window->setFrame(Rect(0, 0, 200, 200));
2669
2670 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2671
2672 constexpr int32_t touchDeviceId = 4;
2673 constexpr int32_t stylusDeviceId = 2;
2674
2675 // Stylus down on the window
2676 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2677 .deviceId(stylusDeviceId)
2678 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2679 .build());
2680 window->consumeMotionEvent(
2681 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2682
2683 // Touch down on window
2684 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2685 .deviceId(touchDeviceId)
2686 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2687 .build());
2688 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2689 .deviceId(touchDeviceId)
2690 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2691 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002692
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002693 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002694
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002695 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002696 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2697 .deviceId(stylusDeviceId)
2698 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2699 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002700 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2701 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002702
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002703 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002704 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2705 .deviceId(touchDeviceId)
2706 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2707 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002708 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002709}
2710
2711/**
2712 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002713 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002714 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002715TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002716 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2717 sp<FakeWindowHandle> window =
2718 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2719 window->setFrame(Rect(0, 0, 200, 200));
2720
2721 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2722
2723 constexpr int32_t touchDeviceId = 4;
2724 constexpr int32_t stylusDeviceId = 2;
2725
2726 // Touch down on window
2727 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2728 .deviceId(touchDeviceId)
2729 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2730 .build());
2731 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2732 .deviceId(touchDeviceId)
2733 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2734 .build());
2735 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2736 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2737
2738 // Stylus hover on the window
2739 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2740 .deviceId(stylusDeviceId)
2741 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2742 .build());
2743 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2744 .deviceId(stylusDeviceId)
2745 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2746 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002747 // Stylus hover movement causes touch to be canceled
2748 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2749 WithCoords(141, 146)));
2750 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2751 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2752 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2753 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002754
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002755 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002756 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2757 .deviceId(touchDeviceId)
2758 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2759 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002760
2761 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002762}
2763
2764/**
2765 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2766 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2767 * become active.
2768 */
2769TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
2770 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2771 sp<FakeWindowHandle> window =
2772 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2773 window->setFrame(Rect(0, 0, 200, 200));
2774
2775 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2776
2777 constexpr int32_t stylusDeviceId1 = 3;
2778 constexpr int32_t stylusDeviceId2 = 5;
2779
2780 // Touch down on window
2781 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2782 .deviceId(stylusDeviceId1)
2783 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2784 .build());
2785 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2786 .deviceId(stylusDeviceId1)
2787 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2788 .build());
2789 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2790 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2791
2792 // Second stylus down
2793 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2794 .deviceId(stylusDeviceId2)
2795 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2796 .build());
2797 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2798 .deviceId(stylusDeviceId2)
2799 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2800 .build());
2801
2802 // First stylus is canceled, second one takes over.
2803 window->consumeMotionEvent(
2804 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2805 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2806 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2807
2808 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2809 .deviceId(stylusDeviceId1)
2810 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2811 .build());
2812 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002813 window->assertNoEvents();
2814}
2815
2816/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002817 * One window. Touch down on the window. Then, stylus down on the window from another device.
2818 * Ensure that is canceled, because stylus down should be preferred over touch.
2819 */
2820TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
2821 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2822 sp<FakeWindowHandle> window =
2823 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2824 window->setFrame(Rect(0, 0, 200, 200));
2825
2826 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2827
2828 constexpr int32_t touchDeviceId = 4;
2829 constexpr int32_t stylusDeviceId = 2;
2830
2831 // Touch down on window
2832 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2833 .deviceId(touchDeviceId)
2834 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2835 .build());
2836 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2837 .deviceId(touchDeviceId)
2838 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2839 .build());
2840 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2841 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2842
2843 // Stylus down on the window
2844 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2845 .deviceId(stylusDeviceId)
2846 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2847 .build());
2848 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2849 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2850
2851 // Subsequent stylus movements are delivered correctly
2852 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2853 .deviceId(stylusDeviceId)
2854 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2855 .build());
2856 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2857 WithCoords(101, 111)));
2858}
2859
2860/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002861 * Two windows: a window on the left and a window on the right.
2862 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2863 * down. Then, on the left window, also place second touch pointer down.
2864 * This test tries to reproduce a crash.
2865 * In the buggy implementation, second pointer down on the left window would cause a crash.
2866 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002867TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002868 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2869 sp<FakeWindowHandle> leftWindow =
2870 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2871 leftWindow->setFrame(Rect(0, 0, 200, 200));
2872
2873 sp<FakeWindowHandle> rightWindow =
2874 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2875 rightWindow->setFrame(Rect(200, 0, 400, 200));
2876
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002877 mDispatcher->onWindowInfosChanged(
2878 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002879
2880 const int32_t touchDeviceId = 4;
2881 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002882
2883 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002884 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2885 .deviceId(mouseDeviceId)
2886 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2887 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002888 leftWindow->consumeMotionEvent(
2889 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2890
2891 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002892 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2893 .deviceId(mouseDeviceId)
2894 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2895 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2896 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002897
2898 leftWindow->consumeMotionEvent(
2899 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2900 leftWindow->consumeMotionEvent(
2901 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2902
Prabir Pradhan678438e2023-04-13 19:32:51 +00002903 mDispatcher->notifyMotion(
2904 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2905 .deviceId(mouseDeviceId)
2906 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2907 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2908 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2909 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002910 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2911
2912 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002913 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2914 .deviceId(touchDeviceId)
2915 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2916 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002917 leftWindow->assertNoEvents();
2918
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002919 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2920
2921 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002922 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2923 .deviceId(touchDeviceId)
2924 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2925 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2926 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002927 // Since this is now a new splittable pointer going down on the left window, and it's coming
2928 // from a different device, the current gesture in the left window (pointer down) should first
2929 // be canceled.
2930 leftWindow->consumeMotionEvent(
2931 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002932 leftWindow->consumeMotionEvent(
2933 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2934 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2935 // current implementation.
2936 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2937 rightWindow->consumeMotionEvent(
2938 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2939
2940 leftWindow->assertNoEvents();
2941 rightWindow->assertNoEvents();
2942}
2943
2944/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002945 * Two windows: a window on the left and a window on the right.
2946 * Mouse is hovered on the left window and stylus is hovered on the right window.
2947 */
2948TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2949 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2950 sp<FakeWindowHandle> leftWindow =
2951 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2952 leftWindow->setFrame(Rect(0, 0, 200, 200));
2953
2954 sp<FakeWindowHandle> rightWindow =
2955 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2956 rightWindow->setFrame(Rect(200, 0, 400, 200));
2957
2958 mDispatcher->onWindowInfosChanged(
2959 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2960
2961 const int32_t stylusDeviceId = 3;
2962 const int32_t mouseDeviceId = 6;
2963
2964 // Start hovering over the left window
2965 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2966 .deviceId(mouseDeviceId)
2967 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2968 .build());
2969 leftWindow->consumeMotionEvent(
2970 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2971
2972 // Stylus hovered on right window
2973 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2974 .deviceId(stylusDeviceId)
2975 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2976 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002977 rightWindow->consumeMotionEvent(
2978 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2979
2980 // Subsequent HOVER_MOVE events are dispatched correctly.
2981 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2982 .deviceId(mouseDeviceId)
2983 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2984 .build());
2985 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002986 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002987
2988 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2989 .deviceId(stylusDeviceId)
2990 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2991 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002992 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002993 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002994
2995 leftWindow->assertNoEvents();
2996 rightWindow->assertNoEvents();
2997}
2998
2999/**
3000 * Three windows: a window on the left and a window on the right.
3001 * And a spy window that's positioned above all of them.
3002 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
3003 * Check the stream that's received by the spy.
3004 */
3005TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
3006 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3007
3008 sp<FakeWindowHandle> spyWindow =
3009 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3010 spyWindow->setFrame(Rect(0, 0, 400, 400));
3011 spyWindow->setTrustedOverlay(true);
3012 spyWindow->setSpy(true);
3013
3014 sp<FakeWindowHandle> leftWindow =
3015 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3016 leftWindow->setFrame(Rect(0, 0, 200, 200));
3017
3018 sp<FakeWindowHandle> rightWindow =
3019 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3020
3021 rightWindow->setFrame(Rect(200, 0, 400, 200));
3022
3023 mDispatcher->onWindowInfosChanged(
3024 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3025
3026 const int32_t stylusDeviceId = 1;
3027 const int32_t touchDeviceId = 2;
3028
3029 // Stylus down on the left window
3030 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3031 .deviceId(stylusDeviceId)
3032 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3033 .build());
3034 leftWindow->consumeMotionEvent(
3035 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3036 spyWindow->consumeMotionEvent(
3037 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3038
3039 // Touch down on the right window
3040 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3041 .deviceId(touchDeviceId)
3042 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3043 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003044 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003045 rightWindow->consumeMotionEvent(
3046 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003047
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003048 // Spy window does not receive touch events, because stylus events take precedence, and it
3049 // already has an active stylus gesture.
3050
3051 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003052 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3053 .deviceId(stylusDeviceId)
3054 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3055 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003056 leftWindow->consumeMotionEvent(
3057 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3058 spyWindow->consumeMotionEvent(
3059 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003060
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003061 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003062 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3063 .deviceId(touchDeviceId)
3064 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
3065 .build());
3066 rightWindow->consumeMotionEvent(
3067 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003068
3069 spyWindow->assertNoEvents();
3070 leftWindow->assertNoEvents();
3071 rightWindow->assertNoEvents();
3072}
3073
3074/**
3075 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3076 * both.
3077 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003078 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003079 * At the same time, left and right should be getting independent streams of hovering and touch,
3080 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003081 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003082TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003083 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3084
3085 sp<FakeWindowHandle> spyWindow =
3086 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3087 spyWindow->setFrame(Rect(0, 0, 400, 400));
3088 spyWindow->setTrustedOverlay(true);
3089 spyWindow->setSpy(true);
3090
3091 sp<FakeWindowHandle> leftWindow =
3092 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3093 leftWindow->setFrame(Rect(0, 0, 200, 200));
3094
3095 sp<FakeWindowHandle> rightWindow =
3096 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3097 rightWindow->setFrame(Rect(200, 0, 400, 200));
3098
3099 mDispatcher->onWindowInfosChanged(
3100 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3101
3102 const int32_t stylusDeviceId = 1;
3103 const int32_t touchDeviceId = 2;
3104
3105 // Stylus hover on the left window
3106 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3107 .deviceId(stylusDeviceId)
3108 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3109 .build());
3110 leftWindow->consumeMotionEvent(
3111 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3112 spyWindow->consumeMotionEvent(
3113 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3114
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003115 // Touch down on the right window. Spy doesn't receive this touch because it already has
3116 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003117 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3118 .deviceId(touchDeviceId)
3119 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3120 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003121 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003122 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003123 rightWindow->consumeMotionEvent(
3124 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3125
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003126 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003127 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3128 .deviceId(stylusDeviceId)
3129 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3130 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003131 leftWindow->consumeMotionEvent(
3132 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003133 spyWindow->consumeMotionEvent(
3134 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003135
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003136 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003137 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3138 .deviceId(touchDeviceId)
3139 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3140 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003141 rightWindow->consumeMotionEvent(
3142 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3143
3144 spyWindow->assertNoEvents();
3145 leftWindow->assertNoEvents();
3146 rightWindow->assertNoEvents();
3147}
3148
3149/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003150 * On a single window, use two different devices: mouse and touch.
3151 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3152 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3153 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3154 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3155 * represent a new gesture.
3156 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003157TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003158 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3159 sp<FakeWindowHandle> window =
3160 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3161 window->setFrame(Rect(0, 0, 400, 400));
3162
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003163 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003164
3165 const int32_t touchDeviceId = 4;
3166 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003167
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003168 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003169 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3170 .deviceId(touchDeviceId)
3171 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3172 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003173 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003174 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3175 .deviceId(touchDeviceId)
3176 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3177 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3178 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003179 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003180 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3181 .deviceId(touchDeviceId)
3182 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3183 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3184 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003185 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3186 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3187 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3188
3189 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003190 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3191 .deviceId(mouseDeviceId)
3192 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3193 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3194 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003195
3196 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003197 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003198 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3199
Prabir Pradhan678438e2023-04-13 19:32:51 +00003200 mDispatcher->notifyMotion(
3201 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3202 .deviceId(mouseDeviceId)
3203 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3204 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3205 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3206 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003207 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3208
3209 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003210 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3211 .deviceId(touchDeviceId)
3212 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3213 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3214 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003215 // Since we already canceled this touch gesture, it will be ignored until a completely new
3216 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3217 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3218 // However, mouse movements should continue to work.
3219 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3220 .deviceId(mouseDeviceId)
3221 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3222 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3223 .build());
3224 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3225
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003226 window->assertNoEvents();
3227}
3228
3229/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003230 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3231 * the injected event.
3232 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003233TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003234 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3235 sp<FakeWindowHandle> window =
3236 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3237 window->setFrame(Rect(0, 0, 400, 400));
3238
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003239 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003240
3241 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003242 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3243 // completion.
3244 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003245 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003246 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3247 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003248 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003249 .build()));
3250 window->consumeMotionEvent(
3251 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3252
3253 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3254 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003255 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3256 .deviceId(touchDeviceId)
3257 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3258 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003259
3260 window->consumeMotionEvent(
3261 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3262 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3263}
3264
3265/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003266 * This test is similar to the test above, but the sequence of injected events is different.
3267 *
3268 * Two windows: a window on the left and a window on the right.
3269 * Mouse is hovered over the left window.
3270 * Next, we tap on the left window, where the cursor was last seen.
3271 *
3272 * After that, we inject one finger down onto the right window, and then a second finger down onto
3273 * the left window.
3274 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3275 * window (first), and then another on the left window (second).
3276 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3277 * In the buggy implementation, second finger down on the left window would cause a crash.
3278 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003279TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003280 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3281 sp<FakeWindowHandle> leftWindow =
3282 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3283 leftWindow->setFrame(Rect(0, 0, 200, 200));
3284
3285 sp<FakeWindowHandle> rightWindow =
3286 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3287 rightWindow->setFrame(Rect(200, 0, 400, 200));
3288
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003289 mDispatcher->onWindowInfosChanged(
3290 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003291
3292 const int32_t mouseDeviceId = 6;
3293 const int32_t touchDeviceId = 4;
3294 // Hover over the left window. Keep the cursor there.
3295 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003296 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003297 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3298 AINPUT_SOURCE_MOUSE)
3299 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003300 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003301 .build()));
3302 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3303
3304 // Tap on left window
3305 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003306 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003307 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3308 AINPUT_SOURCE_TOUCHSCREEN)
3309 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003310 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003311 .build()));
3312
3313 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003314 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003315 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3316 AINPUT_SOURCE_TOUCHSCREEN)
3317 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003318 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003319 .build()));
3320 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3321 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3322 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3323
3324 // First finger down on right window
3325 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003326 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003327 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3328 AINPUT_SOURCE_TOUCHSCREEN)
3329 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003330 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003331 .build()));
3332 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3333
3334 // Second finger down on the left window
3335 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003336 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003337 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3338 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003339 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3340 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003341 .build()));
3342 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3343 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3344
3345 // No more events
3346 leftWindow->assertNoEvents();
3347 rightWindow->assertNoEvents();
3348}
3349
3350/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003351 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3352 * While the touch is down, new hover events from the stylus device should be ignored. After the
3353 * touch is gone, stylus hovering should start working again.
3354 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003355TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003356 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3357 sp<FakeWindowHandle> window =
3358 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3359 window->setFrame(Rect(0, 0, 200, 200));
3360
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003361 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003362
3363 const int32_t stylusDeviceId = 5;
3364 const int32_t touchDeviceId = 4;
3365 // Start hovering with stylus
3366 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003367 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003368 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003369 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003370 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003371 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003372 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003373
3374 // Finger down on the window
3375 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003376 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003377 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003378 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003379 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003380 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003381 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003382
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003383 // Continue hovering with stylus.
3384 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003385 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003386 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3387 AINPUT_SOURCE_STYLUS)
3388 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003389 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003390 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003391 // Hovers continue to work
3392 window->consumeMotionEvent(
3393 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003394
3395 // Lift up the finger
3396 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003397 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003398 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3399 AINPUT_SOURCE_TOUCHSCREEN)
3400 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003401 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003402 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003403
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003404 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003405 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003406 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3407 AINPUT_SOURCE_STYLUS)
3408 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003409 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003410 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003411 window->consumeMotionEvent(
3412 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003413 window->assertNoEvents();
3414}
3415
3416/**
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003417 * If stylus is down anywhere on the screen, then touches should not be delivered to windows that
3418 * have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3419 *
3420 * Two windows: one on the left and one on the right.
3421 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3422 * Stylus down on the left window, and then touch down on the right window.
3423 * Check that the right window doesn't get touches while the stylus is down on the left window.
3424 */
3425TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusDownBlocksTouch) {
3426 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3427 sp<FakeWindowHandle> leftWindow =
3428 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3429 ADISPLAY_ID_DEFAULT);
3430 leftWindow->setFrame(Rect(0, 0, 100, 100));
3431
3432 sp<FakeWindowHandle> sbtRightWindow =
3433 sp<FakeWindowHandle>::make(application, mDispatcher,
3434 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3435 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3436 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3437
3438 mDispatcher->onWindowInfosChanged(
3439 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3440
3441 const int32_t stylusDeviceId = 5;
3442 const int32_t touchDeviceId = 4;
3443
3444 // Stylus down in the left window
3445 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3446 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3447 .deviceId(stylusDeviceId)
3448 .build());
3449 leftWindow->consumeMotionEvent(
3450 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3451
3452 // Finger tap on the right window
3453 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3454 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3455 .deviceId(touchDeviceId)
3456 .build());
3457 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3458 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3459 .deviceId(touchDeviceId)
3460 .build());
3461
3462 // The touch should be blocked, because stylus is down somewhere else on screen!
3463 sbtRightWindow->assertNoEvents();
3464
3465 // Continue stylus motion, and ensure it's not impacted.
3466 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3467 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3468 .deviceId(stylusDeviceId)
3469 .build());
3470 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3471 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3472 .deviceId(stylusDeviceId)
3473 .build());
3474 leftWindow->consumeMotionEvent(
3475 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3476 leftWindow->consumeMotionEvent(
3477 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(stylusDeviceId)));
3478
3479 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3480 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3481 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3482 .deviceId(touchDeviceId)
3483 .build());
3484 sbtRightWindow->consumeMotionEvent(
3485 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3486}
3487
3488/**
3489 * If stylus is hovering anywhere on the screen, then touches should not be delivered to windows
3490 * that have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3491 *
3492 * Two windows: one on the left and one on the right.
3493 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3494 * Stylus hover on the left window, and then touch down on the right window.
3495 * Check that the right window doesn't get touches while the stylus is hovering on the left window.
3496 */
3497TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusHoverBlocksTouch) {
3498 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3499 sp<FakeWindowHandle> leftWindow =
3500 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3501 ADISPLAY_ID_DEFAULT);
3502 leftWindow->setFrame(Rect(0, 0, 100, 100));
3503
3504 sp<FakeWindowHandle> sbtRightWindow =
3505 sp<FakeWindowHandle>::make(application, mDispatcher,
3506 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3507 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3508 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3509
3510 mDispatcher->onWindowInfosChanged(
3511 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3512
3513 const int32_t stylusDeviceId = 5;
3514 const int32_t touchDeviceId = 4;
3515
3516 // Stylus hover in the left window
3517 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3518 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3519 .deviceId(stylusDeviceId)
3520 .build());
3521 leftWindow->consumeMotionEvent(
3522 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3523
3524 // Finger tap on the right window
3525 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3526 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3527 .deviceId(touchDeviceId)
3528 .build());
3529 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3530 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3531 .deviceId(touchDeviceId)
3532 .build());
3533
3534 // The touch should be blocked, because stylus is hovering somewhere else on screen!
3535 sbtRightWindow->assertNoEvents();
3536
3537 // Continue stylus motion, and ensure it's not impacted.
3538 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3539 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3540 .deviceId(stylusDeviceId)
3541 .build());
3542 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3543 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3544 .deviceId(stylusDeviceId)
3545 .build());
3546 leftWindow->consumeMotionEvent(
3547 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3548 leftWindow->consumeMotionEvent(
3549 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3550
3551 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3552 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3553 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3554 .deviceId(touchDeviceId)
3555 .build());
3556 sbtRightWindow->consumeMotionEvent(
3557 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3558}
3559
3560/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003561 * A spy window above a window with no input channel.
3562 * Start hovering with a stylus device, and then tap with it.
3563 * Ensure spy window receives the entire sequence.
3564 */
3565TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3566 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3567 sp<FakeWindowHandle> spyWindow =
3568 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3569 spyWindow->setFrame(Rect(0, 0, 200, 200));
3570 spyWindow->setTrustedOverlay(true);
3571 spyWindow->setSpy(true);
3572 sp<FakeWindowHandle> window =
3573 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3574 window->setNoInputChannel(true);
3575 window->setFrame(Rect(0, 0, 200, 200));
3576
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003577 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003578
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003579 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003580 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3581 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3582 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003583 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3584 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003585 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3586 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3587 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003588 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3589
3590 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003591 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3592 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3593 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003594 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3595
3596 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003597 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3598 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3599 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003600 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3601
3602 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003603 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3604 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3605 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003606 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3607 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003608 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3609 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3610 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003611 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3612
3613 // No more events
3614 spyWindow->assertNoEvents();
3615 window->assertNoEvents();
3616}
3617
3618/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003619 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3620 * rejected. But since we already have an ongoing gesture, this event should be processed.
3621 * This prevents inconsistent events being handled inside the dispatcher.
3622 */
3623TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3624 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3625
3626 sp<FakeWindowHandle> window =
3627 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3628 window->setFrame(Rect(0, 0, 200, 200));
3629
3630 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3631
3632 // Start hovering with stylus
3633 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3634 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3635 .build());
3636 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3637
3638 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3639 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3640 .build();
3641 // Make this 'hoverExit' event stale
3642 mFakePolicy->setStaleEventTimeout(100ms);
3643 std::this_thread::sleep_for(100ms);
3644
3645 // It shouldn't be dropped by the dispatcher, even though it's stale.
3646 mDispatcher->notifyMotion(hoverExit);
3647 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3648
3649 // Stylus starts hovering again! There should be no crash.
3650 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3651 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3652 .build());
3653 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3654}
3655
3656/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003657 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3658 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3659 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3660 * While the mouse is down, new move events from the touch device should be ignored.
3661 */
3662TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3663 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3664 sp<FakeWindowHandle> spyWindow =
3665 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3666 spyWindow->setFrame(Rect(0, 0, 200, 200));
3667 spyWindow->setTrustedOverlay(true);
3668 spyWindow->setSpy(true);
3669 sp<FakeWindowHandle> window =
3670 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3671 window->setFrame(Rect(0, 0, 200, 200));
3672
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003673 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003674
3675 const int32_t mouseDeviceId = 7;
3676 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003677
3678 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003679 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3680 .deviceId(mouseDeviceId)
3681 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3682 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003683 spyWindow->consumeMotionEvent(
3684 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3685 window->consumeMotionEvent(
3686 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3687
3688 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003689 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3690 .deviceId(touchDeviceId)
3691 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3692 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003693 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3694 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3695 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3696 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3697
Prabir Pradhan678438e2023-04-13 19:32:51 +00003698 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3699 .deviceId(touchDeviceId)
3700 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3701 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003702 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3703 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3704
3705 // Pilfer the stream
3706 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3707 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3708
Prabir Pradhan678438e2023-04-13 19:32:51 +00003709 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3710 .deviceId(touchDeviceId)
3711 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3712 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003713 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3714
3715 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003716 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3717 .deviceId(mouseDeviceId)
3718 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3719 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3720 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003721
3722 spyWindow->consumeMotionEvent(
3723 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3724 spyWindow->consumeMotionEvent(
3725 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3726 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3727
Prabir Pradhan678438e2023-04-13 19:32:51 +00003728 mDispatcher->notifyMotion(
3729 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3730 .deviceId(mouseDeviceId)
3731 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3732 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3733 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3734 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003735 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3736 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3737
3738 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003739 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3740 .deviceId(mouseDeviceId)
3741 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3742 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3743 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003744 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3745 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3746
3747 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003748 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3749 .deviceId(touchDeviceId)
3750 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3751 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003752
3753 // No more events
3754 spyWindow->assertNoEvents();
3755 window->assertNoEvents();
3756}
3757
3758/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003759 * On the display, have a single window, and also an area where there's no window.
3760 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3761 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3762 */
3763TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3764 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3765 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003766 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003767
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003768 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003769
3770 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003771 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003772
3773 mDispatcher->waitForIdle();
3774 window->assertNoEvents();
3775
3776 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003777 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003778 mDispatcher->waitForIdle();
3779 window->consumeMotionDown();
3780}
3781
3782/**
3783 * Same test as above, but instead of touching the empty space, the first touch goes to
3784 * non-touchable window.
3785 */
3786TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3787 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3788 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003789 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003790 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3791 window1->setTouchable(false);
3792 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003793 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003794 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3795
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003796 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003797
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003798 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003799 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003800
3801 mDispatcher->waitForIdle();
3802 window1->assertNoEvents();
3803 window2->assertNoEvents();
3804
3805 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003806 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003807 mDispatcher->waitForIdle();
3808 window2->consumeMotionDown();
3809}
3810
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003811/**
3812 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3813 * to the event time of the first ACTION_DOWN sent to the particular window.
3814 */
3815TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3816 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3817 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003818 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003819 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3820 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003821 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003822 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3823
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003824 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003825
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003826 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003827 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003828
3829 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003830
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08003831 std::unique_ptr<MotionEvent> motionEvent1 = window1->consumeMotionEvent();
3832 ASSERT_NE(nullptr, motionEvent1);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003833 window2->assertNoEvents();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08003834 nsecs_t downTimeForWindow1 = motionEvent1->getDownTime();
3835 ASSERT_EQ(motionEvent1->getDownTime(), motionEvent1->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003836
3837 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003838 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003839 mDispatcher->waitForIdle();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08003840 std::unique_ptr<MotionEvent> motionEvent2 = window2->consumeMotionEvent();
3841 ASSERT_NE(nullptr, motionEvent2);
3842 nsecs_t downTimeForWindow2 = motionEvent2->getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003843 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08003844 ASSERT_EQ(motionEvent2->getDownTime(), motionEvent2->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003845
3846 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003847 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003848 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003849 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003850
3851 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003852 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003853 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003854 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003855
3856 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3857 window1->consumeMotionMove();
3858 window1->assertNoEvents();
3859
3860 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003861 mDispatcher->notifyMotion(
3862 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003863 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003864 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003865
Prabir Pradhan678438e2023-04-13 19:32:51 +00003866 mDispatcher->notifyMotion(
3867 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003868 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003869 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003870}
3871
Garfield Tandf26e862020-07-01 20:18:19 -07003872TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003873 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003874 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003875 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003876 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003877 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003878 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003879 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003880
3881 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3882
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003883 mDispatcher->onWindowInfosChanged(
3884 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003885
3886 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003887 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003888 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003889 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3890 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003891 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003892 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003893 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003894
3895 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003896 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003897 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003898 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3899 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003900 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003901 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003902 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3903 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003904
3905 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003906 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003907 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003908 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3909 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003910 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003911 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003912 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3913 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003914
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003915 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003916 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003917 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3918 AINPUT_SOURCE_MOUSE)
3919 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3920 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003921 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003922 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003923 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003924
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003925 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003926 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003927 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3928 AINPUT_SOURCE_MOUSE)
3929 .buttonState(0)
3930 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003931 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003932 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003933 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003934
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003935 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003936 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003937 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3938 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003939 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003940 .build()));
3941 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3942
3943 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003944 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003945 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003946 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3947 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003948 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003949 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003950 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003951
3952 // No more events
3953 windowLeft->assertNoEvents();
3954 windowRight->assertNoEvents();
3955}
3956
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003957/**
3958 * Put two fingers down (and don't release them) and click the mouse button.
3959 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3960 * currently active gesture should be canceled, and the new one should proceed.
3961 */
3962TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3963 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3964 sp<FakeWindowHandle> window =
3965 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3966 window->setFrame(Rect(0, 0, 600, 800));
3967
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003968 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003969
3970 const int32_t touchDeviceId = 4;
3971 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003972
3973 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003974 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3975 .deviceId(touchDeviceId)
3976 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3977 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003978
Prabir Pradhan678438e2023-04-13 19:32:51 +00003979 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3980 .deviceId(touchDeviceId)
3981 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3982 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3983 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003984 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3985 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3986
3987 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003988 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3989 .deviceId(mouseDeviceId)
3990 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3991 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3992 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003993 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3994 WithPointerCount(2u)));
3995 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3996
Prabir Pradhan678438e2023-04-13 19:32:51 +00003997 mDispatcher->notifyMotion(
3998 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3999 .deviceId(mouseDeviceId)
4000 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4001 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4002 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4003 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004004 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4005
4006 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4007 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004008 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4009 .deviceId(touchDeviceId)
4010 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4011 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4012 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004013 window->assertNoEvents();
4014}
4015
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004016TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
4017 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4018
4019 sp<FakeWindowHandle> spyWindow =
4020 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4021 spyWindow->setFrame(Rect(0, 0, 600, 800));
4022 spyWindow->setTrustedOverlay(true);
4023 spyWindow->setSpy(true);
4024 sp<FakeWindowHandle> window =
4025 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4026 window->setFrame(Rect(0, 0, 600, 800));
4027
4028 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004029 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004030
4031 // Send mouse cursor to the window
4032 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004033 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004034 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4035 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004036 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004037 .build()));
4038
4039 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4040 WithSource(AINPUT_SOURCE_MOUSE)));
4041 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4042 WithSource(AINPUT_SOURCE_MOUSE)));
4043
4044 window->assertNoEvents();
4045 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004046}
4047
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004048TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
4049 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4050
4051 sp<FakeWindowHandle> spyWindow =
4052 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4053 spyWindow->setFrame(Rect(0, 0, 600, 800));
4054 spyWindow->setTrustedOverlay(true);
4055 spyWindow->setSpy(true);
4056 sp<FakeWindowHandle> window =
4057 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4058 window->setFrame(Rect(0, 0, 600, 800));
4059
4060 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004061 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004062
4063 // Send mouse cursor to the window
4064 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004065 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004066 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4067 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004068 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004069 .build()));
4070
4071 // Move mouse cursor
4072 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004073 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004074 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4075 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004076 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004077 .build()));
4078
4079 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4080 WithSource(AINPUT_SOURCE_MOUSE)));
4081 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4082 WithSource(AINPUT_SOURCE_MOUSE)));
4083 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4084 WithSource(AINPUT_SOURCE_MOUSE)));
4085 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4086 WithSource(AINPUT_SOURCE_MOUSE)));
4087 // Touch down on the window
4088 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004089 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004090 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4091 AINPUT_SOURCE_TOUCHSCREEN)
4092 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004093 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004094 .build()));
4095 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4096 WithSource(AINPUT_SOURCE_MOUSE)));
4097 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4098 WithSource(AINPUT_SOURCE_MOUSE)));
4099 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4100 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4101 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4102 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4103
4104 // pilfer the motion, retaining the gesture on the spy window.
4105 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4106 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4107 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4108
4109 // Touch UP on the window
4110 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004111 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004112 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4113 AINPUT_SOURCE_TOUCHSCREEN)
4114 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004115 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004116 .build()));
4117 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4118 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4119
4120 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4121 // to send a new gesture. It should again go to both windows (spy and the window below), just
4122 // like the first gesture did, before pilfering. The window configuration has not changed.
4123
4124 // One more tap - DOWN
4125 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004126 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004127 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4128 AINPUT_SOURCE_TOUCHSCREEN)
4129 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004130 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004131 .build()));
4132 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4133 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4134 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4135 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4136
4137 // Touch UP on the window
4138 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004139 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004140 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4141 AINPUT_SOURCE_TOUCHSCREEN)
4142 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004143 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004144 .build()));
4145 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4146 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4147 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4148 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4149
4150 window->assertNoEvents();
4151 spyWindow->assertNoEvents();
4152}
4153
Garfield Tandf26e862020-07-01 20:18:19 -07004154// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
4155// directly in this test.
4156TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004157 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07004158 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004159 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004160 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004161
4162 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4163
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004164 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004165
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004166 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004167 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004168 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4169 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004170 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004171 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004172 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004173 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004174 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004175 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004176 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4177 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004178 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004179 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004180 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4181 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004182
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004183 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004184 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004185 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4186 AINPUT_SOURCE_MOUSE)
4187 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4188 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004189 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004190 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004191 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004192
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004193 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004194 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004195 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4196 AINPUT_SOURCE_MOUSE)
4197 .buttonState(0)
4198 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004199 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004200 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004201 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004202
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004203 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004204 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004205 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4206 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004207 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004208 .build()));
4209 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
4210
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07004211 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
4212 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
4213 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004214 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004215 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
4216 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004217 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004218 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004219 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004220}
4221
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004222/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004223 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
4224 * is generated.
4225 */
4226TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
4227 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4228 sp<FakeWindowHandle> window =
4229 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4230 window->setFrame(Rect(0, 0, 1200, 800));
4231
4232 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4233
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004234 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004235
4236 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004237 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004238 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4239 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004240 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004241 .build()));
4242 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4243
4244 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004245 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004246 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4247}
4248
4249/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004250 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4251 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004252TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4253 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4254 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004255 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4256 sp<FakeWindowHandle> window =
4257 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4258 window->setFrame(Rect(0, 0, 1200, 800));
4259
4260 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4261
4262 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4263
4264 MotionEventBuilder hoverEnterBuilder =
4265 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4266 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4267 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4268 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4269 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4270 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4271 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4272 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4273 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4274}
4275
4276/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004277 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4278 */
4279TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4280 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4281 sp<FakeWindowHandle> window =
4282 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4283 window->setFrame(Rect(0, 0, 100, 100));
4284
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004285 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004286
4287 const int32_t mouseDeviceId = 7;
4288 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004289
4290 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004291 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4292 .deviceId(mouseDeviceId)
4293 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4294 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004295 window->consumeMotionEvent(
4296 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4297
4298 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004299 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4300 .deviceId(touchDeviceId)
4301 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4302 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004303
4304 window->consumeMotionEvent(
4305 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4306 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4307}
4308
4309/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004310 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004311 * The tap causes a HOVER_EXIT event to be generated because the current event
4312 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004313 */
4314TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4315 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4316 sp<FakeWindowHandle> window =
4317 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4318 window->setFrame(Rect(0, 0, 100, 100));
4319
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004320 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004321 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4322 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4323 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004324 ASSERT_NO_FATAL_FAILURE(
4325 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4326 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004327
4328 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004329 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4330 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4331 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004332 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004333 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4334 WithSource(AINPUT_SOURCE_MOUSE))));
4335
4336 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004337 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4338 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4339
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004340 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4341 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4342 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004343 ASSERT_NO_FATAL_FAILURE(
4344 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4345 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4346}
4347
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004348TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4349 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4350 sp<FakeWindowHandle> windowDefaultDisplay =
4351 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4352 ADISPLAY_ID_DEFAULT);
4353 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4354 sp<FakeWindowHandle> windowSecondDisplay =
4355 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4356 SECOND_DISPLAY_ID);
4357 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4358
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004359 mDispatcher->onWindowInfosChanged(
4360 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004361
4362 // Set cursor position in window in default display and check that hover enter and move
4363 // events are generated.
4364 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004365 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004366 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4367 AINPUT_SOURCE_MOUSE)
4368 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004369 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004370 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004371 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004372
4373 // Remove all windows in secondary display and check that no event happens on window in
4374 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004375 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4376
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004377 windowDefaultDisplay->assertNoEvents();
4378
4379 // Move cursor position in window in default display and check that only hover move
4380 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004381 mDispatcher->onWindowInfosChanged(
4382 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004383 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004384 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004385 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4386 AINPUT_SOURCE_MOUSE)
4387 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004388 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004389 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004390 windowDefaultDisplay->consumeMotionEvent(
4391 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4392 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004393 windowDefaultDisplay->assertNoEvents();
4394}
4395
Garfield Tan00f511d2019-06-12 16:55:40 -07004396TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004397 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004398
4399 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004400 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004401 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004402 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004403 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004404 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004405
4406 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4407
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004408 mDispatcher->onWindowInfosChanged(
4409 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004410
4411 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4412 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004413 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004414 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004415 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004416 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004417 windowRight->assertNoEvents();
4418}
4419
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004420TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004421 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004422 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4423 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004424 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004425
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004426 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004427 setFocusedWindow(window);
4428
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004429 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004430
Prabir Pradhan678438e2023-04-13 19:32:51 +00004431 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004432
4433 // Window should receive key down event.
4434 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4435
4436 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4437 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004438 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004439 window->consumeKeyUp(ADISPLAY_ID_DEFAULT, AKEY_EVENT_FLAG_CANCELED);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004440}
4441
4442TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004443 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004444 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4445 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004446
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004447 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004448
Prabir Pradhan678438e2023-04-13 19:32:51 +00004449 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4450 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004451
4452 // Window should receive motion down event.
4453 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4454
4455 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4456 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004457 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004458 window->consumeMotionEvent(
4459 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004460}
4461
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004462TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4463 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4464 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4465 "Fake Window", ADISPLAY_ID_DEFAULT);
4466
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004467 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004468
4469 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4470 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4471 .build());
4472
4473 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4474
4475 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4476 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4477 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4478
4479 // After the device has been reset, a new hovering stream can be sent to the window
4480 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4481 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4482 .build());
4483 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4484}
4485
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004486TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4487 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004488 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4489 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004490 window->setFocusable(true);
4491
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004492 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004493 setFocusedWindow(window);
4494
4495 window->consumeFocusEvent(true);
4496
Prabir Pradhan678438e2023-04-13 19:32:51 +00004497 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004498 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4499 const nsecs_t injectTime = keyArgs.eventTime;
4500 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004501 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004502 // The dispatching time should be always greater than or equal to intercept key timeout.
4503 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4504 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4505 std::chrono::nanoseconds(interceptKeyTimeout).count());
4506}
4507
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004508/**
4509 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4510 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004511TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4512 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004513 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4514 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004515 window->setFocusable(true);
4516
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004517 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004518 setFocusedWindow(window);
4519
4520 window->consumeFocusEvent(true);
4521
Prabir Pradhan678438e2023-04-13 19:32:51 +00004522 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004523 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004524
4525 // Set a value that's significantly larger than the default consumption timeout. If the
4526 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4527 mFakePolicy->setInterceptKeyTimeout(600ms);
4528 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4529 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004530 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4531}
4532
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004533/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004534 * Two windows. First is a regular window. Second does not overlap with the first, and has
4535 * WATCH_OUTSIDE_TOUCH.
4536 * Both windows are owned by the same UID.
4537 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4538 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4539 */
4540TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4541 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004542 sp<FakeWindowHandle> window =
4543 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004544 window->setFrame(Rect{0, 0, 100, 100});
4545
4546 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004547 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004548 ADISPLAY_ID_DEFAULT);
4549 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4550 outsideWindow->setWatchOutsideTouch(true);
4551 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004552 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004553
4554 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004555 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4556 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4557 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004558 window->consumeMotionDown();
4559 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4560 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4561 outsideWindow->consumeMotionEvent(
4562 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00004563
4564 // Ensure outsideWindow doesn't get any more events for the gesture.
4565 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4566 ADISPLAY_ID_DEFAULT, {PointF{51, 51}}));
4567 window->consumeMotionMove();
4568 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004569}
4570
4571/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004572 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4573 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4574 * ACTION_OUTSIDE event is sent per gesture.
4575 */
4576TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4577 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4578 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004579 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4580 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004581 window->setWatchOutsideTouch(true);
4582 window->setFrame(Rect{0, 0, 100, 100});
4583 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004584 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4585 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004586 secondWindow->setFrame(Rect{100, 100, 200, 200});
4587 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004588 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4589 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004590 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004591 mDispatcher->onWindowInfosChanged(
4592 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004593
4594 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004595 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4596 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4597 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004598 window->assertNoEvents();
4599 secondWindow->assertNoEvents();
4600
4601 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4602 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004603 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4604 ADISPLAY_ID_DEFAULT,
4605 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004606 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4607 window->consumeMotionEvent(
4608 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004609 secondWindow->consumeMotionDown();
4610 thirdWindow->assertNoEvents();
4611
4612 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4613 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004614 mDispatcher->notifyMotion(
4615 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4616 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004617 window->assertNoEvents();
4618 secondWindow->consumeMotionMove();
4619 thirdWindow->consumeMotionDown();
4620}
4621
Prabir Pradhan814fe082022-07-22 20:22:18 +00004622TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4623 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004624 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4625 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004626 window->setFocusable(true);
4627
Patrick Williamsd828f302023-04-28 17:52:08 -05004628 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004629 setFocusedWindow(window);
4630
4631 window->consumeFocusEvent(true);
4632
Prabir Pradhan678438e2023-04-13 19:32:51 +00004633 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4634 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4635 mDispatcher->notifyKey(keyDown);
4636 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004637
4638 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4639 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4640
4641 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004642 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004643
4644 window->consumeFocusEvent(false);
4645
Prabir Pradhan678438e2023-04-13 19:32:51 +00004646 mDispatcher->notifyKey(keyDown);
4647 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004648 window->assertNoEvents();
4649}
4650
Arthur Hung96483742022-11-15 03:30:48 +00004651TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4652 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4653 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4654 "Fake Window", ADISPLAY_ID_DEFAULT);
4655 // Ensure window is non-split and have some transform.
4656 window->setPreventSplitting(true);
4657 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004658 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004659
4660 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004661 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004662 {50, 50}))
4663 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4664 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4665
4666 const MotionEvent secondFingerDownEvent =
4667 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4668 .displayId(ADISPLAY_ID_DEFAULT)
4669 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004670 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4671 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004672 .build();
4673 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004674 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004675 InputEventInjectionSync::WAIT_FOR_RESULT))
4676 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4677
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004678 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
4679 ASSERT_NE(nullptr, event);
4680 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4681 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4682 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4683 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4684 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
Arthur Hung96483742022-11-15 03:30:48 +00004685}
4686
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004687/**
4688 * Two windows: a splittable and a non-splittable.
4689 * The non-splittable window shouldn't receive any "incomplete" gestures.
4690 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4691 * The second pointer should be dropped because the initial window is splittable, so it won't get
4692 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4693 * "incomplete" gestures.
4694 */
4695TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4696 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4697 sp<FakeWindowHandle> leftWindow =
4698 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4699 ADISPLAY_ID_DEFAULT);
4700 leftWindow->setPreventSplitting(false);
4701 leftWindow->setFrame(Rect(0, 0, 100, 100));
4702 sp<FakeWindowHandle> rightWindow =
4703 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4704 ADISPLAY_ID_DEFAULT);
4705 rightWindow->setPreventSplitting(true);
4706 rightWindow->setFrame(Rect(100, 100, 200, 200));
4707 mDispatcher->onWindowInfosChanged(
4708 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4709
4710 // Touch down on left, splittable window
4711 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4712 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4713 .build());
4714 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4715
4716 mDispatcher->notifyMotion(
4717 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4718 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4719 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4720 .build());
4721 leftWindow->assertNoEvents();
4722 rightWindow->assertNoEvents();
4723}
4724
Harry Cuttsb166c002023-05-09 13:06:05 +00004725TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4726 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4727 sp<FakeWindowHandle> window =
4728 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4729 window->setFrame(Rect(0, 0, 400, 400));
4730 sp<FakeWindowHandle> trustedOverlay =
4731 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4732 ADISPLAY_ID_DEFAULT);
4733 trustedOverlay->setSpy(true);
4734 trustedOverlay->setTrustedOverlay(true);
4735
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004736 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004737
4738 // Start a three-finger touchpad swipe
4739 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4740 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4741 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4742 .build());
4743 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4744 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4745 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4746 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4747 .build());
4748 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4749 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4750 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4751 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4752 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4753 .build());
4754
4755 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4756 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4757 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4758
4759 // Move the swipe a bit
4760 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4761 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4762 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4763 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4764 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4765 .build());
4766
4767 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4768
4769 // End the swipe
4770 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4771 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4772 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4773 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4774 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4775 .build());
4776 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4777 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4778 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4779 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4780 .build());
4781 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4782 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4783 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4784 .build());
4785
4786 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4787 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4788 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4789
4790 window->assertNoEvents();
4791}
4792
4793TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4794 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4795 sp<FakeWindowHandle> window =
4796 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4797 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004798 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004799
4800 // Start a three-finger touchpad swipe
4801 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4802 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4803 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4804 .build());
4805 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4806 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4807 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4808 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4809 .build());
4810 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4811 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4812 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4813 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4814 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4815 .build());
4816
4817 // Move the swipe a bit
4818 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4819 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4820 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4821 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4822 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4823 .build());
4824
4825 // End the swipe
4826 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4827 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4828 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4829 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4830 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4831 .build());
4832 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4833 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4834 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4835 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4836 .build());
4837 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4838 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4839 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4840 .build());
4841
4842 window->assertNoEvents();
4843}
4844
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004845/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004846 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4847 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004848 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004849 */
4850TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4851 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4852 sp<FakeWindowHandle> window =
4853 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4854 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004855 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004856
4857 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4858 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4859 .downTime(baseTime + 10)
4860 .eventTime(baseTime + 10)
4861 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4862 .build());
4863
4864 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4865
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004866 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004867 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004868
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004869 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004870
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004871 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4872 .downTime(baseTime + 10)
4873 .eventTime(baseTime + 30)
4874 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4875 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4876 .build());
4877
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004878 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4879
4880 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004881 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4882 .downTime(baseTime + 10)
4883 .eventTime(baseTime + 40)
4884 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4885 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4886 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004887
4888 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4889
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004890 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4891 .downTime(baseTime + 10)
4892 .eventTime(baseTime + 50)
4893 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4894 .build());
4895
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004896 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4897
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004898 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4899 .downTime(baseTime + 60)
4900 .eventTime(baseTime + 60)
4901 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4902 .build());
4903
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004904 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004905}
4906
4907/**
Hu Guo771a7692023-09-17 20:51:08 +08004908 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4909 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4910 * its coordinates should be converted by the transform of the windows of target screen.
4911 */
4912TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4913 // This case will create a window and a spy window on the default display and mirror
4914 // window on the second display. cancel event is sent through spy window pilferPointers
4915 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4916
4917 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4918 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4919 spyWindowDefaultDisplay->setTrustedOverlay(true);
4920 spyWindowDefaultDisplay->setSpy(true);
4921
4922 sp<FakeWindowHandle> windowDefaultDisplay =
4923 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4924 ADISPLAY_ID_DEFAULT);
4925 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4926
4927 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4928 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4929
4930 // Add the windows to the dispatcher
4931 mDispatcher->onWindowInfosChanged(
4932 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4933 *windowSecondDisplay->getInfo()},
4934 {},
4935 0,
4936 0});
4937
4938 // Send down to ADISPLAY_ID_DEFAULT
4939 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4940 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4941 {100, 100}))
4942 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4943
4944 spyWindowDefaultDisplay->consumeMotionDown();
4945 windowDefaultDisplay->consumeMotionDown();
4946
4947 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4948
4949 // windowDefaultDisplay gets cancel
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004950 std::unique_ptr<MotionEvent> event = windowDefaultDisplay->consumeMotionEvent();
4951 ASSERT_NE(nullptr, event);
4952 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
Hu Guo771a7692023-09-17 20:51:08 +08004953
4954 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4955 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4956 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4957 // SECOND_DISPLAY_ID, the x and y coordinates are 200
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004958 EXPECT_EQ(100, event->getX(0));
4959 EXPECT_EQ(100, event->getY(0));
Hu Guo771a7692023-09-17 20:51:08 +08004960}
4961
4962/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004963 * Ensure the correct coordinate spaces are used by InputDispatcher.
4964 *
4965 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4966 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4967 * space.
4968 */
4969class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4970public:
4971 void SetUp() override {
4972 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004973 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004974 }
4975
4976 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4977 gui::DisplayInfo info;
4978 info.displayId = displayId;
4979 info.transform = transform;
4980 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004981 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004982 }
4983
4984 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4985 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004986 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004987 }
4988
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004989 void removeAllWindowsAndDisplays() {
4990 mDisplayInfos.clear();
4991 mWindowInfos.clear();
4992 }
4993
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004994 // Set up a test scenario where the display has a scaled projection and there are two windows
4995 // on the display.
4996 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4997 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4998 // respectively.
4999 ui::Transform displayTransform;
5000 displayTransform.set(2, 0, 0, 4);
5001 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5002
5003 std::shared_ptr<FakeApplicationHandle> application =
5004 std::make_shared<FakeApplicationHandle>();
5005
5006 // Add two windows to the display. Their frames are represented in the display space.
5007 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005008 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5009 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005010 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
5011 addWindow(firstWindow);
5012
5013 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005014 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5015 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005016 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
5017 addWindow(secondWindow);
5018 return {std::move(firstWindow), std::move(secondWindow)};
5019 }
5020
5021private:
5022 std::vector<gui::DisplayInfo> mDisplayInfos;
5023 std::vector<gui::WindowInfo> mWindowInfos;
5024};
5025
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005026TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005027 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5028 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005029 // selected so that if the hit test was performed with the point and the bounds being in
5030 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005031 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5032 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5033 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005034
5035 firstWindow->consumeMotionDown();
5036 secondWindow->assertNoEvents();
5037}
5038
5039// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
5040// the event should be treated as being in the logical display space.
5041TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
5042 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5043 // Send down to the first window. The point is represented in the logical display space. The
5044 // point is selected so that if the hit test was done in logical display space, then it would
5045 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005046 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005047 PointF{75 * 2, 55 * 4});
5048
5049 firstWindow->consumeMotionDown();
5050 secondWindow->assertNoEvents();
5051}
5052
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005053// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
5054// event should be treated as being in the logical display space.
5055TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
5056 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5057
5058 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5059 ui::Transform injectedEventTransform;
5060 injectedEventTransform.set(matrix);
5061 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
5062 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
5063
5064 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5065 .displayId(ADISPLAY_ID_DEFAULT)
5066 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005067 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005068 .x(untransformedPoint.x)
5069 .y(untransformedPoint.y))
5070 .build();
5071 event.transform(matrix);
5072
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005073 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005074 InputEventInjectionSync::WAIT_FOR_RESULT);
5075
5076 firstWindow->consumeMotionDown();
5077 secondWindow->assertNoEvents();
5078}
5079
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005080TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
5081 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5082
5083 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005084 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5085 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5086 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005087
5088 firstWindow->assertNoEvents();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005089 std::unique_ptr<MotionEvent> event = secondWindow->consumeMotionEvent();
5090 ASSERT_NE(nullptr, event);
5091 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005092
5093 // Ensure that the events from the "getRaw" API are in logical display coordinates.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005094 EXPECT_EQ(300, event->getRawX(0));
5095 EXPECT_EQ(880, event->getRawY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005096
5097 // Ensure that the x and y values are in the window's coordinate space.
5098 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
5099 // the logical display space. This will be the origin of the window space.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005100 EXPECT_EQ(100, event->getX(0));
5101 EXPECT_EQ(80, event->getY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005102}
5103
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005104TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
5105 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5106 // The monitor will always receive events in the logical display's coordinate space, because
5107 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00005108 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005109
5110 // Send down to the first window.
5111 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5112 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5113 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5114 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5115
5116 // Second pointer goes down on second window.
5117 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5118 ADISPLAY_ID_DEFAULT,
5119 {PointF{50, 100}, PointF{150, 220}}));
5120 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
5121 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
5122 {1, PointF{300, 880}}};
5123 monitor.consumeMotionEvent(
5124 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
5125
5126 mDispatcher->cancelCurrentTouch();
5127
5128 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5129 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
5130 monitor.consumeMotionEvent(
5131 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
5132}
5133
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005134TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
5135 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5136
5137 // Send down to the first window.
5138 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5139 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5140 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5141
5142 // The pointer is transferred to the second window, and the second window receives it in the
5143 // correct coordinate space.
5144 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5145 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5146 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
5147}
5148
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005149TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
5150 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5151
5152 // Send hover move to the second window, and ensure it shows up as hover enter.
5153 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5154 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5155 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5156 WithCoords(100, 80), WithRawCoords(300, 880)));
5157
5158 // Touch down at the same location and ensure a hover exit is synthesized.
5159 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5160 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5161 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5162 WithRawCoords(300, 880)));
5163 secondWindow->consumeMotionEvent(
5164 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5165 secondWindow->assertNoEvents();
5166 firstWindow->assertNoEvents();
5167}
5168
Prabir Pradhan453ae732023-10-13 14:30:14 +00005169// Same as above, but while the window is being mirrored.
5170TEST_F(InputDispatcherDisplayProjectionTest,
5171 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
5172 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5173
5174 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5175 ui::Transform secondDisplayTransform;
5176 secondDisplayTransform.set(matrix);
5177 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5178
5179 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5180 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5181 addWindow(secondWindowClone);
5182
5183 // Send hover move to the second window, and ensure it shows up as hover enter.
5184 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5185 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5186 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5187 WithCoords(100, 80), WithRawCoords(300, 880)));
5188
5189 // Touch down at the same location and ensure a hover exit is synthesized for the correct
5190 // display.
5191 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5192 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5193 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5194 WithRawCoords(300, 880)));
5195 secondWindow->consumeMotionEvent(
5196 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5197 secondWindow->assertNoEvents();
5198 firstWindow->assertNoEvents();
5199}
5200
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005201TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
5202 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5203
5204 // Send hover enter to second window
5205 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5206 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5207 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5208 WithCoords(100, 80), WithRawCoords(300, 880)));
5209
5210 mDispatcher->cancelCurrentTouch();
5211
5212 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5213 WithRawCoords(300, 880)));
5214 secondWindow->assertNoEvents();
5215 firstWindow->assertNoEvents();
5216}
5217
Prabir Pradhan453ae732023-10-13 14:30:14 +00005218// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00005219TEST_F(InputDispatcherDisplayProjectionTest,
5220 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
5221 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5222
5223 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5224 ui::Transform secondDisplayTransform;
5225 secondDisplayTransform.set(matrix);
5226 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5227
5228 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5229 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5230 addWindow(secondWindowClone);
5231
5232 // Send hover enter to second window
5233 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5234 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5235 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5236 WithCoords(100, 80), WithRawCoords(300, 880),
5237 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5238
5239 mDispatcher->cancelCurrentTouch();
5240
5241 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
5242 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5243 WithRawCoords(300, 880),
5244 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5245 secondWindow->assertNoEvents();
5246 firstWindow->assertNoEvents();
5247}
5248
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005249/** Ensure consistent behavior of InputDispatcher in all orientations. */
5250class InputDispatcherDisplayOrientationFixture
5251 : public InputDispatcherDisplayProjectionTest,
5252 public ::testing::WithParamInterface<ui::Rotation> {};
5253
5254// This test verifies the touchable region of a window for all rotations of the display by tapping
5255// in different locations on the display, specifically points close to the four corners of a
5256// window.
5257TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
5258 constexpr static int32_t displayWidth = 400;
5259 constexpr static int32_t displayHeight = 800;
5260
5261 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5262
5263 const auto rotation = GetParam();
5264
5265 // Set up the display with the specified rotation.
5266 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5267 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5268 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5269 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5270 logicalDisplayWidth, logicalDisplayHeight);
5271 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5272
5273 // Create a window with its bounds determined in the logical display.
5274 const Rect frameInLogicalDisplay(100, 100, 200, 300);
5275 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
5276 sp<FakeWindowHandle> window =
5277 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5278 window->setFrame(frameInDisplay, displayTransform);
5279 addWindow(window);
5280
5281 // The following points in logical display space should be inside the window.
5282 static const std::array<vec2, 4> insidePoints{
5283 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5284 for (const auto pointInsideWindow : insidePoints) {
5285 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
5286 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005287 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5288 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5289 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005290 window->consumeMotionDown();
5291
Prabir Pradhan678438e2023-04-13 19:32:51 +00005292 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5293 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5294 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005295 window->consumeMotionUp();
5296 }
5297
5298 // The following points in logical display space should be outside the window.
5299 static const std::array<vec2, 5> outsidePoints{
5300 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
5301 for (const auto pointOutsideWindow : outsidePoints) {
5302 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
5303 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005304 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5305 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5306 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005307
Prabir Pradhan678438e2023-04-13 19:32:51 +00005308 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5309 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5310 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005311 }
5312 window->assertNoEvents();
5313}
5314
5315// Run the precision tests for all rotations.
5316INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
5317 InputDispatcherDisplayOrientationFixture,
5318 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
5319 ui::ROTATION_270),
5320 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
5321 return ftl::enum_string(testParamInfo.param);
5322 });
5323
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005324using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
5325 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005326
5327class TransferTouchFixture : public InputDispatcherTest,
5328 public ::testing::WithParamInterface<TransferFunction> {};
5329
5330TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07005331 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005332
5333 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005334 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005335 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5336 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005337 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005338 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005339 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5340 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005341 sp<FakeWindowHandle> wallpaper =
5342 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
5343 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005344 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005345 mDispatcher->onWindowInfosChanged(
5346 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005347
5348 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005349 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5350 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005351
Svet Ganov5d3bc372020-01-26 23:11:07 -08005352 // Only the first window should get the down event
5353 firstWindow->consumeMotionDown();
5354 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005355 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005356
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005357 // Transfer touch to the second window
5358 TransferFunction f = GetParam();
5359 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5360 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005361 // The first window gets cancel and the second gets down
5362 firstWindow->consumeMotionCancel();
5363 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005364 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005365
5366 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005367 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5368 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005369 // The first window gets no events and the second gets up
5370 firstWindow->assertNoEvents();
5371 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005372 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005373}
5374
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005375/**
5376 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
5377 * from. When we have spy windows, there are several windows to choose from: either spy, or the
5378 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
5379 * natural to the user.
5380 * In this test, we are sending a pointer to both spy window and first window. We then try to
5381 * transfer touch to the second window. The dispatcher should identify the first window as the
5382 * one that should lose the gesture, and therefore the action should be to move the gesture from
5383 * the first window to the second.
5384 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
5385 * the other API, as well.
5386 */
5387TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5388 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5389
5390 // Create a couple of windows + a spy window
5391 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005392 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005393 spyWindow->setTrustedOverlay(true);
5394 spyWindow->setSpy(true);
5395 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005396 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005397 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005398 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005399
5400 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005401 mDispatcher->onWindowInfosChanged(
5402 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005403
5404 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005405 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5406 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005407 // Only the first window and spy should get the down event
5408 spyWindow->consumeMotionDown();
5409 firstWindow->consumeMotionDown();
5410
5411 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
5412 // if f === 'transferTouch'.
5413 TransferFunction f = GetParam();
5414 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5415 ASSERT_TRUE(success);
5416 // The first window gets cancel and the second gets down
5417 firstWindow->consumeMotionCancel();
5418 secondWindow->consumeMotionDown();
5419
5420 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005421 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5422 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005423 // The first window gets no events and the second+spy get up
5424 firstWindow->assertNoEvents();
5425 spyWindow->consumeMotionUp();
5426 secondWindow->consumeMotionUp();
5427}
5428
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005429TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005430 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005431
5432 PointF touchPoint = {10, 10};
5433
5434 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005435 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005436 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5437 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005438 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005439 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005440 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5441 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005442 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005443
5444 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005445 mDispatcher->onWindowInfosChanged(
5446 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005447
5448 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005449 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5450 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5451 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005452 // Only the first window should get the down event
5453 firstWindow->consumeMotionDown();
5454 secondWindow->assertNoEvents();
5455
5456 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005457 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5458 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005459 // Only the first window should get the pointer down event
5460 firstWindow->consumeMotionPointerDown(1);
5461 secondWindow->assertNoEvents();
5462
5463 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005464 TransferFunction f = GetParam();
5465 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5466 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005467 // The first window gets cancel and the second gets down and pointer down
5468 firstWindow->consumeMotionCancel();
5469 secondWindow->consumeMotionDown();
5470 secondWindow->consumeMotionPointerDown(1);
5471
5472 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005473 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5474 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005475 // The first window gets nothing and the second gets pointer up
5476 firstWindow->assertNoEvents();
5477 secondWindow->consumeMotionPointerUp(1);
5478
5479 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005480 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5481 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005482 // The first window gets nothing and the second gets up
5483 firstWindow->assertNoEvents();
5484 secondWindow->consumeMotionUp();
5485}
5486
Arthur Hungc539dbb2022-12-08 07:45:36 +00005487TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5488 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5489
5490 // Create a couple of windows
5491 sp<FakeWindowHandle> firstWindow =
5492 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5493 ADISPLAY_ID_DEFAULT);
5494 firstWindow->setDupTouchToWallpaper(true);
5495 sp<FakeWindowHandle> secondWindow =
5496 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5497 ADISPLAY_ID_DEFAULT);
5498 secondWindow->setDupTouchToWallpaper(true);
5499
5500 sp<FakeWindowHandle> wallpaper1 =
5501 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5502 wallpaper1->setIsWallpaper(true);
5503
5504 sp<FakeWindowHandle> wallpaper2 =
5505 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5506 wallpaper2->setIsWallpaper(true);
5507 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005508 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5509 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5510 {},
5511 0,
5512 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005513
5514 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005515 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5516 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005517
5518 // Only the first window should get the down event
5519 firstWindow->consumeMotionDown();
5520 secondWindow->assertNoEvents();
5521 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5522 wallpaper2->assertNoEvents();
5523
5524 // Transfer touch focus to the second window
5525 TransferFunction f = GetParam();
5526 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5527 ASSERT_TRUE(success);
5528
5529 // The first window gets cancel and the second gets down
5530 firstWindow->consumeMotionCancel();
5531 secondWindow->consumeMotionDown();
5532 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5533 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5534
5535 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005536 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5537 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005538 // The first window gets no events and the second gets up
5539 firstWindow->assertNoEvents();
5540 secondWindow->consumeMotionUp();
5541 wallpaper1->assertNoEvents();
5542 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5543}
5544
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005545// For the cases of single pointer touch and two pointers non-split touch, the api's
5546// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5547// for the case where there are multiple pointers split across several windows.
5548INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5549 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005550 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5551 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005552 return dispatcher->transferTouch(destChannelToken,
5553 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005554 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005555 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5556 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005557 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005558 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005559 }));
5560
Svet Ganov5d3bc372020-01-26 23:11:07 -08005561TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005562 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005563
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005564 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005565 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5566 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005567 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005568
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005569 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005570 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5571 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005572 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005573
5574 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005575 mDispatcher->onWindowInfosChanged(
5576 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005577
5578 PointF pointInFirst = {300, 200};
5579 PointF pointInSecond = {300, 600};
5580
5581 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005582 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5583 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5584 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005585 // Only the first window should get the down event
5586 firstWindow->consumeMotionDown();
5587 secondWindow->assertNoEvents();
5588
5589 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005590 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5591 ADISPLAY_ID_DEFAULT,
5592 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005593 // The first window gets a move and the second a down
5594 firstWindow->consumeMotionMove();
5595 secondWindow->consumeMotionDown();
5596
5597 // Transfer touch focus to the second window
5598 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5599 // The first window gets cancel and the new gets pointer down (it already saw down)
5600 firstWindow->consumeMotionCancel();
5601 secondWindow->consumeMotionPointerDown(1);
5602
5603 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005604 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5605 ADISPLAY_ID_DEFAULT,
5606 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005607 // The first window gets nothing and the second gets pointer up
5608 firstWindow->assertNoEvents();
5609 secondWindow->consumeMotionPointerUp(1);
5610
5611 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005612 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5613 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005614 // The first window gets nothing and the second gets up
5615 firstWindow->assertNoEvents();
5616 secondWindow->consumeMotionUp();
5617}
5618
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005619// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5620// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5621// touch is not supported, so the touch should continue on those windows and the transferred-to
5622// window should get nothing.
5623TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5624 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5625
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005626 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005627 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5628 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005629 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005630
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005631 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005632 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5633 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005634 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005635
5636 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005637 mDispatcher->onWindowInfosChanged(
5638 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005639
5640 PointF pointInFirst = {300, 200};
5641 PointF pointInSecond = {300, 600};
5642
5643 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005644 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5645 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5646 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005647 // Only the first window should get the down event
5648 firstWindow->consumeMotionDown();
5649 secondWindow->assertNoEvents();
5650
5651 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005652 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5653 ADISPLAY_ID_DEFAULT,
5654 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005655 // The first window gets a move and the second a down
5656 firstWindow->consumeMotionMove();
5657 secondWindow->consumeMotionDown();
5658
5659 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005660 const bool transferred =
5661 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005662 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5663 ASSERT_FALSE(transferred);
5664 firstWindow->assertNoEvents();
5665 secondWindow->assertNoEvents();
5666
5667 // The rest of the dispatch should proceed as normal
5668 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005669 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5670 ADISPLAY_ID_DEFAULT,
5671 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005672 // The first window gets MOVE and the second gets pointer up
5673 firstWindow->consumeMotionMove();
5674 secondWindow->consumeMotionUp();
5675
5676 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005677 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5678 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005679 // The first window gets nothing and the second gets up
5680 firstWindow->consumeMotionUp();
5681 secondWindow->assertNoEvents();
5682}
5683
Arthur Hungabbb9d82021-09-01 14:52:30 +00005684// This case will create two windows and one mirrored window on the default display and mirror
5685// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5686// the windows info of second display before default display.
5687TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5688 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5689 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005690 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005691 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005692 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005693 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005694 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005695
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005696 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005697 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005698
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005699 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005700 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005701
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005702 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005703 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005704
5705 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005706 mDispatcher->onWindowInfosChanged(
5707 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5708 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5709 *secondWindowInPrimary->getInfo()},
5710 {},
5711 0,
5712 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005713
5714 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005715 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005716 {50, 50}))
5717 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5718
5719 // Window should receive motion event.
5720 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5721
5722 // Transfer touch focus
5723 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5724 secondWindowInPrimary->getToken()));
5725 // The first window gets cancel.
5726 firstWindowInPrimary->consumeMotionCancel();
5727 secondWindowInPrimary->consumeMotionDown();
5728
5729 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005730 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005731 ADISPLAY_ID_DEFAULT, {150, 50}))
5732 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5733 firstWindowInPrimary->assertNoEvents();
5734 secondWindowInPrimary->consumeMotionMove();
5735
5736 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005737 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005738 {150, 50}))
5739 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5740 firstWindowInPrimary->assertNoEvents();
5741 secondWindowInPrimary->consumeMotionUp();
5742}
5743
5744// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5745// 'transferTouch' api.
5746TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5747 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5748 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005749 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005750 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005751 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005752 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005753 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005754
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005755 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005756 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005757
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005758 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005759 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005760
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005761 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005762 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005763
5764 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005765 mDispatcher->onWindowInfosChanged(
5766 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5767 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5768 *secondWindowInPrimary->getInfo()},
5769 {},
5770 0,
5771 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005772
5773 // Touch on second display.
5774 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005775 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5776 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005777 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5778
5779 // Window should receive motion event.
5780 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5781
5782 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005783 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005784
5785 // The first window gets cancel.
5786 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5787 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5788
5789 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005790 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005791 SECOND_DISPLAY_ID, {150, 50}))
5792 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5793 firstWindowInPrimary->assertNoEvents();
5794 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5795
5796 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005797 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005798 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5799 firstWindowInPrimary->assertNoEvents();
5800 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5801}
5802
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005803TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005804 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005805 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5806 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005807
Vishnu Nair47074b82020-08-14 11:54:47 -07005808 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005809 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005810 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005811
5812 window->consumeFocusEvent(true);
5813
Prabir Pradhan678438e2023-04-13 19:32:51 +00005814 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005815
5816 // Window should receive key down event.
5817 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005818
5819 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005820 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005821 mFakePolicy->assertUserActivityPoked();
5822}
5823
5824TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5825 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5826 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5827 "Fake Window", ADISPLAY_ID_DEFAULT);
5828
5829 window->setDisableUserActivity(true);
5830 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005831 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005832 setFocusedWindow(window);
5833
5834 window->consumeFocusEvent(true);
5835
5836 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5837
5838 // Window should receive key down event.
5839 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5840
5841 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005842 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005843 mFakePolicy->assertUserActivityNotPoked();
5844}
5845
5846TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5847 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5848 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5849 "Fake Window", ADISPLAY_ID_DEFAULT);
5850
5851 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005852 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005853 setFocusedWindow(window);
5854
5855 window->consumeFocusEvent(true);
5856
5857 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5858 mDispatcher->waitForIdle();
5859
5860 // System key is not passed down
5861 window->assertNoEvents();
5862
5863 // Should have poked user activity
5864 mFakePolicy->assertUserActivityPoked();
5865}
5866
5867TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5868 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5869 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5870 "Fake Window", ADISPLAY_ID_DEFAULT);
5871
5872 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005873 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005874 setFocusedWindow(window);
5875
5876 window->consumeFocusEvent(true);
5877
5878 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5879 mDispatcher->waitForIdle();
5880
5881 // System key is not passed down
5882 window->assertNoEvents();
5883
5884 // Should have poked user activity
5885 mFakePolicy->assertUserActivityPoked();
5886}
5887
5888TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5889 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5890 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5891 "Fake Window", ADISPLAY_ID_DEFAULT);
5892
5893 window->setDisableUserActivity(true);
5894 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005895 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005896 setFocusedWindow(window);
5897
5898 window->consumeFocusEvent(true);
5899
5900 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5901 mDispatcher->waitForIdle();
5902
5903 // System key is not passed down
5904 window->assertNoEvents();
5905
5906 // Should have poked user activity
5907 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005908}
5909
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005910TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5911 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5912 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5913 "Fake Window", ADISPLAY_ID_DEFAULT);
5914
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005915 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005916
5917 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005918 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005919 ADISPLAY_ID_DEFAULT, {100, 100}))
5920 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5921
5922 window->consumeMotionEvent(
5923 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5924
5925 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005926 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005927 mFakePolicy->assertUserActivityPoked();
5928}
5929
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005930TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005931 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005932 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5933 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005934
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005935 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005936
Prabir Pradhan678438e2023-04-13 19:32:51 +00005937 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005938 mDispatcher->waitForIdle();
5939
5940 window->assertNoEvents();
5941}
5942
5943// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5944TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005945 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005946 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5947 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005948
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005949 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005950
5951 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005952 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005953 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005954 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5955 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005956
5957 // Window should receive only the motion event
5958 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5959 window->assertNoEvents(); // Key event or focus event will not be received
5960}
5961
arthurhungea3f4fc2020-12-21 23:18:53 +08005962TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5963 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5964
arthurhungea3f4fc2020-12-21 23:18:53 +08005965 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005966 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5967 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005968 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005969
arthurhungea3f4fc2020-12-21 23:18:53 +08005970 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005971 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5972 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005973 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005974
5975 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005976 mDispatcher->onWindowInfosChanged(
5977 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005978
5979 PointF pointInFirst = {300, 200};
5980 PointF pointInSecond = {300, 600};
5981
5982 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005983 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5984 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5985 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005986 // Only the first window should get the down event
5987 firstWindow->consumeMotionDown();
5988 secondWindow->assertNoEvents();
5989
5990 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005991 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5992 ADISPLAY_ID_DEFAULT,
5993 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005994 // The first window gets a move and the second a down
5995 firstWindow->consumeMotionMove();
5996 secondWindow->consumeMotionDown();
5997
5998 // Send pointer cancel to the second window
5999 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006000 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08006001 {pointInFirst, pointInSecond});
6002 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00006003 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08006004 // The first window gets move and the second gets cancel.
6005 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
6006 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
6007
6008 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00006009 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6010 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08006011 // The first window gets up and the second gets nothing.
6012 firstWindow->consumeMotionUp();
6013 secondWindow->assertNoEvents();
6014}
6015
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006016TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
6017 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6018
6019 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006020 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006021 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006022 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
6023 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
6024 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
6025
Harry Cutts33476232023-01-30 19:57:29 +00006026 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006027 window->assertNoEvents();
6028 mDispatcher->waitForIdle();
6029}
6030
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006031using InputDispatcherMonitorTest = InputDispatcherTest;
6032
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006033/**
6034 * Two entities that receive touch: A window, and a global monitor.
6035 * The touch goes to the window, and then the window disappears.
6036 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
6037 * for the monitor, as well.
6038 * 1. foregroundWindow
6039 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
6040 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006041TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006042 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6043 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006044 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006045
Prabir Pradhanfb549072023-10-05 19:17:36 +00006046 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006047
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006048 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006049 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006050 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006051 {100, 200}))
6052 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6053
6054 // Both the foreground window and the global monitor should receive the touch down
6055 window->consumeMotionDown();
6056 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6057
6058 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006059 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006060 ADISPLAY_ID_DEFAULT, {110, 200}))
6061 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6062
6063 window->consumeMotionMove();
6064 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6065
6066 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006067 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006068 window->consumeMotionCancel();
6069 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
6070
6071 // If more events come in, there will be no more foreground window to send them to. This will
6072 // cause a cancel for the monitor, as well.
6073 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006074 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006075 ADISPLAY_ID_DEFAULT, {120, 200}))
6076 << "Injection should fail because the window was removed";
6077 window->assertNoEvents();
6078 // Global monitor now gets the cancel
6079 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6080}
6081
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006082TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07006083 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006084 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6085 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006086 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006087
Prabir Pradhanfb549072023-10-05 19:17:36 +00006088 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006089
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006090 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006091 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006092 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00006093 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006094 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006095}
6096
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006097TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00006098 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006099
Chris Yea209fde2020-07-22 13:54:51 -07006100 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006101 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6102 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006103 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006104
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006105 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006106 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006107 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08006108 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006109 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006110
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006111 // Pilfer pointers from the monitor.
6112 // This should not do anything and the window should continue to receive events.
6113 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00006114
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006115 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006116 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006117 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006118 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006119
6120 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6121 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006122}
6123
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006124TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07006125 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006126 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6127 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006128 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07006129 window->setWindowOffset(20, 40);
6130 window->setWindowTransform(0, 1, -1, 0);
6131
Prabir Pradhanfb549072023-10-05 19:17:36 +00006132 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07006133
6134 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006135 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07006136 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6137 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006138 std::unique_ptr<MotionEvent> event = monitor.consumeMotion();
6139 ASSERT_NE(nullptr, event);
Evan Rosky84f07f02021-04-16 10:42:42 -07006140 // Even though window has transform, gesture monitor must not.
6141 ASSERT_EQ(ui::Transform(), event->getTransform());
6142}
6143
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006144TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00006145 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00006146 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00006147
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006148 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006149 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006150 << "Injection should fail if there is a monitor, but no touchable window";
6151 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00006152}
6153
Linnan Lid8150952024-01-26 18:07:17 +00006154/**
6155 * Two displays
6156 * The first monitor has a foreground window, a monitor
6157 * The second window has only one monitor.
6158 * We first inject a Down event into the first display, this injection should succeed and both
6159 * the foreground window and monitor should receive a down event, then inject a Down event into
6160 * the second display as well, this injection should fail, at this point, the first display
6161 * window and monitor should not receive a cancel or any other event.
6162 * Continue to inject Move and UP events to the first display, the events should be received
6163 * normally by the foreground window and monitor.
6164 */
6165TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCanceledWhenAnotherEmptyDisplayReceiveEvents) {
6166 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6167 sp<FakeWindowHandle> window =
6168 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6169
6170 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6171 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
6172
6173 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6174 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6175 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6176 {100, 200}))
6177 << "The down event injected into the first display should succeed";
6178
6179 window->consumeMotionDown();
6180 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006181
6182 ASSERT_EQ(InputEventInjectionResult::FAILED,
6183 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6184 {100, 200}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006185 << "The down event injected into the second display should fail since there's no "
6186 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006187
6188 // Continue to inject event to first display.
6189 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6190 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6191 ADISPLAY_ID_DEFAULT, {110, 220}))
6192 << "The move event injected into the first display should succeed";
6193
6194 window->consumeMotionMove();
6195 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006196
6197 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6198 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6199 {110, 220}))
6200 << "The up event injected into the first display should succeed";
6201
6202 window->consumeMotionUp();
6203 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006204
6205 window->assertNoEvents();
6206 monitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00006207 secondMonitor.assertNoEvents();
6208}
6209
6210/**
6211 * Two displays
6212 * There is a monitor and foreground window on each display.
6213 * First, we inject down events into each of the two displays, at this point, the foreground windows
6214 * and monitors on both displays should receive down events.
6215 * At this point, the foreground window of the second display goes away, the gone window should
6216 * receive the cancel event, and the other windows and monitors should not receive any events.
6217 * Inject a move event into the second display. At this point, the injection should fail because
6218 * the second display no longer has a foreground window. At this point, the monitor on the second
6219 * display should receive a cancel event, and any windows or monitors on the first display should
6220 * not receive any events, and any subsequent injection of events into the second display should
6221 * also fail.
6222 * Continue to inject events into the first display, and the events should all be injected
6223 * successfully and received normally.
6224 */
6225TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCancelWhenAnotherDisplayMonitorTouchCanceled) {
6226 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6227 sp<FakeWindowHandle> window =
6228 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6229 sp<FakeWindowHandle> secondWindow =
6230 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondForeground",
6231 SECOND_DISPLAY_ID);
6232
6233 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6234 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
6235
6236 // There is a foreground window on both displays.
6237 mDispatcher->onWindowInfosChanged({{*window->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
6238 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6239 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6240 {100, 200}))
6241 << "The down event injected into the first display should succeed";
6242
6243 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6244 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006245
6246 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6247 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6248 {100, 200}))
6249 << "The down event injected into the second display should succeed";
6250
Linnan Lid8150952024-01-26 18:07:17 +00006251 secondWindow->consumeMotionDown(SECOND_DISPLAY_ID);
6252 secondMonitor.consumeMotionDown(SECOND_DISPLAY_ID);
6253
6254 // Now second window is gone away.
6255 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6256
6257 // The gone window should receive a cancel, and the monitor on the second display should not
6258 // receive any events.
Linnan Lid8150952024-01-26 18:07:17 +00006259 secondWindow->consumeMotionCancel(SECOND_DISPLAY_ID);
6260 secondMonitor.assertNoEvents();
6261
6262 ASSERT_EQ(InputEventInjectionResult::FAILED,
6263 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6264 SECOND_DISPLAY_ID, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006265 << "The move event injected into the second display should fail because there's no "
6266 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006267 // Now the monitor on the second display should receive a cancel event.
6268 secondMonitor.consumeMotionCancel(SECOND_DISPLAY_ID);
Linnan Lid8150952024-01-26 18:07:17 +00006269
6270 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6271 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6272 ADISPLAY_ID_DEFAULT, {110, 200}))
6273 << "The move event injected into the first display should succeed";
6274
6275 window->consumeMotionMove();
6276 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006277
6278 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006279 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6280 {110, 220}))
6281 << "The up event injected into the second display should fail because there's no "
6282 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006283
6284 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6285 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6286 {110, 220}))
6287 << "The up event injected into the first display should succeed";
6288
6289 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6290 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006291
Linnan Lid8150952024-01-26 18:07:17 +00006292 window->assertNoEvents();
6293 monitor.assertNoEvents();
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006294 secondWindow->assertNoEvents();
6295 secondMonitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00006296}
6297
6298/**
6299 * One display with transform
6300 * There is a foreground window and a monitor on the display
6301 * Inject down event and move event sequentially, the foreground window and monitor can receive down
6302 * event and move event, then let the foreground window go away, the foreground window receives
6303 * cancel event, inject move event again, the monitor receives cancel event, all the events received
6304 * by the monitor should be with the same transform as the display
6305 */
6306TEST_F(InputDispatcherMonitorTest, MonitorTouchCancelEventWithDisplayTransform) {
6307 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6308 sp<FakeWindowHandle> window =
6309 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6310 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6311
6312 ui::Transform transform;
6313 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6314
6315 gui::DisplayInfo displayInfo;
6316 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6317 displayInfo.transform = transform;
6318
6319 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
6320
6321 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6322 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6323 {100, 200}))
6324 << "The down event injected should succeed";
6325
6326 window->consumeMotionDown();
6327 std::unique_ptr<MotionEvent> downMotionEvent = monitor.consumeMotion();
6328 EXPECT_EQ(transform, downMotionEvent->getTransform());
6329 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, downMotionEvent->getAction());
6330
6331 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6332 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6333 ADISPLAY_ID_DEFAULT, {110, 220}))
6334 << "The move event injected should succeed";
6335
6336 window->consumeMotionMove();
6337 std::unique_ptr<MotionEvent> moveMotionEvent = monitor.consumeMotion();
6338 EXPECT_EQ(transform, moveMotionEvent->getTransform());
6339 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, moveMotionEvent->getAction());
6340
6341 // Let foreground window gone
6342 mDispatcher->onWindowInfosChanged({{}, {displayInfo}, 0, 0});
6343
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006344 // Foreground window should receive a cancel event, but not the monitor.
Linnan Lid8150952024-01-26 18:07:17 +00006345 window->consumeMotionCancel();
Linnan Lid8150952024-01-26 18:07:17 +00006346
6347 ASSERT_EQ(InputEventInjectionResult::FAILED,
6348 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6349 ADISPLAY_ID_DEFAULT, {110, 220}))
6350 << "The move event injected should failed";
6351 // Now foreground should not receive any events, but monitor should receive a cancel event
6352 // with transform that same as display's display.
Linnan Lid8150952024-01-26 18:07:17 +00006353 std::unique_ptr<MotionEvent> cancelMotionEvent = monitor.consumeMotion();
6354 EXPECT_EQ(transform, cancelMotionEvent->getTransform());
6355 EXPECT_EQ(ADISPLAY_ID_DEFAULT, cancelMotionEvent->getDisplayId());
6356 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, cancelMotionEvent->getAction());
6357
6358 // Other event inject to this display should fail.
6359 ASSERT_EQ(InputEventInjectionResult::FAILED,
6360 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6361 ADISPLAY_ID_DEFAULT, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006362 << "The up event injected should fail because the touched window was removed";
Linnan Lid8150952024-01-26 18:07:17 +00006363 window->assertNoEvents();
6364 monitor.assertNoEvents();
6365}
6366
chaviw81e2bb92019-12-18 15:03:51 -08006367TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006368 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006369 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6370 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08006371
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006372 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08006373
6374 NotifyMotionArgs motionArgs =
6375 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6376 ADISPLAY_ID_DEFAULT);
6377
Prabir Pradhan678438e2023-04-13 19:32:51 +00006378 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08006379 // Window should receive motion down event.
6380 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6381
6382 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08006383 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08006384 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6385 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
6386 motionArgs.pointerCoords[0].getX() - 10);
6387
Prabir Pradhan678438e2023-04-13 19:32:51 +00006388 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006389 window->consumeMotionMove(ADISPLAY_ID_DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08006390}
6391
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006392/**
6393 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
6394 * the device default right away. In the test scenario, we check both the default value,
6395 * and the action of enabling / disabling.
6396 */
6397TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07006398 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006399 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6400 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08006401 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006402
6403 // Set focused application.
6404 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006405 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006406
6407 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006408 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006409 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006410 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006411
6412 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006413 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006414 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006415 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006416
6417 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006418 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006419 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006420 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07006421 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006422 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006423 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006424 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006425
6426 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006427 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006428 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006429 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006430
6431 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006432 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006433 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006434 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07006435 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006436 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006437 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006438 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006439
6440 window->assertNoEvents();
6441}
6442
Gang Wange9087892020-01-07 12:17:14 -05006443TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006444 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006445 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6446 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05006447
6448 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006449 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05006450
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006451 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006452 setFocusedWindow(window);
6453
Harry Cutts33476232023-01-30 19:57:29 +00006454 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05006455
Prabir Pradhan678438e2023-04-13 19:32:51 +00006456 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
6457 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05006458
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006459 std::unique_ptr<KeyEvent> event = window->consumeKey();
6460 ASSERT_NE(event, nullptr);
6461 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Gang Wange9087892020-01-07 12:17:14 -05006462 ASSERT_NE(verified, nullptr);
6463 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
6464
6465 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
6466 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
6467 ASSERT_EQ(keyArgs.source, verified->source);
6468 ASSERT_EQ(keyArgs.displayId, verified->displayId);
6469
6470 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
6471
6472 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05006473 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006474 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05006475 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
6476 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
6477 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
6478 ASSERT_EQ(0, verifiedKey.repeatCount);
6479}
6480
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006481TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006482 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006483 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6484 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006485
6486 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6487
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006488 ui::Transform transform;
6489 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6490
6491 gui::DisplayInfo displayInfo;
6492 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6493 displayInfo.transform = transform;
6494
Patrick Williamsd828f302023-04-28 17:52:08 -05006495 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006496
Prabir Pradhan678438e2023-04-13 19:32:51 +00006497 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006498 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6499 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006500 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006501
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006502 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
6503 ASSERT_NE(nullptr, event);
6504 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006505 ASSERT_NE(verified, nullptr);
6506 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
6507
6508 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
6509 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
6510 EXPECT_EQ(motionArgs.source, verified->source);
6511 EXPECT_EQ(motionArgs.displayId, verified->displayId);
6512
6513 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
6514
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006515 const vec2 rawXY =
6516 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
6517 motionArgs.pointerCoords[0].getXYValue());
6518 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
6519 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006520 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006521 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006522 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006523 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
6524 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
6525}
6526
chaviw09c8d2d2020-08-24 15:48:26 -07006527/**
6528 * Ensure that separate calls to sign the same data are generating the same key.
6529 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
6530 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
6531 * tests.
6532 */
6533TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
6534 KeyEvent event = getTestKeyEvent();
6535 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6536
6537 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
6538 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
6539 ASSERT_EQ(hmac1, hmac2);
6540}
6541
6542/**
6543 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6544 */
6545TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6546 KeyEvent event = getTestKeyEvent();
6547 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6548 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6549
6550 verifiedEvent.deviceId += 1;
6551 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6552
6553 verifiedEvent.source += 1;
6554 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6555
6556 verifiedEvent.eventTimeNanos += 1;
6557 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6558
6559 verifiedEvent.displayId += 1;
6560 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6561
6562 verifiedEvent.action += 1;
6563 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6564
6565 verifiedEvent.downTimeNanos += 1;
6566 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6567
6568 verifiedEvent.flags += 1;
6569 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6570
6571 verifiedEvent.keyCode += 1;
6572 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6573
6574 verifiedEvent.scanCode += 1;
6575 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6576
6577 verifiedEvent.metaState += 1;
6578 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6579
6580 verifiedEvent.repeatCount += 1;
6581 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6582}
6583
Vishnu Nair958da932020-08-21 17:12:37 -07006584TEST_F(InputDispatcherTest, SetFocusedWindow) {
6585 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6586 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006587 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006588 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006589 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006590 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6591
6592 // Top window is also focusable but is not granted focus.
6593 windowTop->setFocusable(true);
6594 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006595 mDispatcher->onWindowInfosChanged(
6596 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006597 setFocusedWindow(windowSecond);
6598
6599 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006600 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006601 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006602
6603 // Focused window should receive event.
6604 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6605 windowTop->assertNoEvents();
6606}
6607
6608TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
6609 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6610 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006611 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006612 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6613
6614 window->setFocusable(true);
6615 // Release channel for window is no longer valid.
6616 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006617 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006618 setFocusedWindow(window);
6619
6620 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006621 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006622
6623 // window channel is invalid, so it should not receive any input event.
6624 window->assertNoEvents();
6625}
6626
6627TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
6628 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6629 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006630 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006631 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006632 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6633
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006634 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006635 setFocusedWindow(window);
6636
6637 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006638 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006639
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006640 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006641 window->assertNoEvents();
6642}
6643
6644TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6645 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6646 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006647 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006648 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006649 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006650 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6651
6652 windowTop->setFocusable(true);
6653 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006654 mDispatcher->onWindowInfosChanged(
6655 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006656 setFocusedWindow(windowTop);
6657 windowTop->consumeFocusEvent(true);
6658
Chavi Weingarten847e8512023-03-29 00:26:09 +00006659 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006660 mDispatcher->onWindowInfosChanged(
6661 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006662 windowSecond->consumeFocusEvent(true);
6663 windowTop->consumeFocusEvent(false);
6664
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006665 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006666 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006667
6668 // Focused window should receive event.
6669 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6670}
6671
Chavi Weingarten847e8512023-03-29 00:26:09 +00006672TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006673 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6674 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006675 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006676 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006677 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006678 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6679
6680 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006681 windowSecond->setFocusable(false);
6682 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006683 mDispatcher->onWindowInfosChanged(
6684 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006685 setFocusedWindow(windowTop);
6686 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006687
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006688 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006689 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006690
6691 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006692 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006693 windowSecond->assertNoEvents();
6694}
6695
6696TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6697 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6698 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006699 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006700 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006701 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6702 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006703 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6704
6705 window->setFocusable(true);
6706 previousFocusedWindow->setFocusable(true);
6707 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006708 mDispatcher->onWindowInfosChanged(
6709 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006710 setFocusedWindow(previousFocusedWindow);
6711 previousFocusedWindow->consumeFocusEvent(true);
6712
6713 // Requesting focus on invisible window takes focus from currently focused window.
6714 setFocusedWindow(window);
6715 previousFocusedWindow->consumeFocusEvent(false);
6716
6717 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006718 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006719 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6720 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006721
6722 // Window does not get focus event or key down.
6723 window->assertNoEvents();
6724
6725 // Window becomes visible.
6726 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006727 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006728
6729 // Window receives focus event.
6730 window->consumeFocusEvent(true);
6731 // Focused window receives key down.
6732 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6733}
6734
Vishnu Nair599f1412021-06-21 10:39:58 -07006735TEST_F(InputDispatcherTest, DisplayRemoved) {
6736 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6737 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006738 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006739 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6740
6741 // window is granted focus.
6742 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006743 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006744 setFocusedWindow(window);
6745 window->consumeFocusEvent(true);
6746
6747 // When a display is removed window loses focus.
6748 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6749 window->consumeFocusEvent(false);
6750}
6751
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006752/**
6753 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6754 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6755 * of the 'slipperyEnterWindow'.
6756 *
6757 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6758 * a way so that the touched location is no longer covered by the top window.
6759 *
6760 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6761 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6762 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6763 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6764 * with ACTION_DOWN).
6765 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6766 * window moved itself away from the touched location and had Flag::SLIPPERY.
6767 *
6768 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6769 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6770 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6771 *
6772 * In this test, we ensure that the event received by the bottom window has
6773 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6774 */
6775TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006776 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006777 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006778
6779 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6780 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6781
6782 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006783 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006784 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006785 // Make sure this one overlaps the bottom window
6786 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6787 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6788 // one. Windows with the same owner are not considered to be occluding each other.
6789 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6790
6791 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006792 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006793 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6794
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006795 mDispatcher->onWindowInfosChanged(
6796 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006797
6798 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006799 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6800 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6801 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006802 slipperyExitWindow->consumeMotionDown();
6803 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006804 mDispatcher->onWindowInfosChanged(
6805 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006806
Prabir Pradhan678438e2023-04-13 19:32:51 +00006807 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6808 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6809 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006810
6811 slipperyExitWindow->consumeMotionCancel();
6812
6813 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6814 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6815}
6816
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006817/**
6818 * Two windows, one on the left and another on the right. The left window is slippery. The right
6819 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6820 * touch moves from the left window into the right window, the gesture should continue to go to the
6821 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6822 * reproduces a crash.
6823 */
6824TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6825 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6826
6827 sp<FakeWindowHandle> leftSlipperyWindow =
6828 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6829 leftSlipperyWindow->setSlippery(true);
6830 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6831
6832 sp<FakeWindowHandle> rightDropTouchesWindow =
6833 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6834 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6835 rightDropTouchesWindow->setDropInput(true);
6836
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006837 mDispatcher->onWindowInfosChanged(
6838 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006839
6840 // Start touch in the left window
6841 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6842 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6843 .build());
6844 leftSlipperyWindow->consumeMotionDown();
6845
6846 // And move it into the right window
6847 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6848 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6849 .build());
6850
6851 // Since the right window isn't eligible to receive input, touch does not slip.
6852 // The left window continues to receive the gesture.
6853 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6854 rightDropTouchesWindow->assertNoEvents();
6855}
6856
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006857/**
6858 * A single window is on screen first. Touch is injected into that window. Next, a second window
6859 * appears. Since the first window is slippery, touch will move from the first window to the second.
6860 */
6861TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6862 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6863 sp<FakeWindowHandle> originalWindow =
6864 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6865 originalWindow->setFrame(Rect(0, 0, 200, 200));
6866 originalWindow->setSlippery(true);
6867
6868 sp<FakeWindowHandle> appearingWindow =
6869 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6870 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6871
6872 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6873
6874 // Touch down on the original window
6875 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6876 injectMotionEvent(*mDispatcher,
6877 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6878 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6879 .build()));
6880 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6881
6882 // Now, a new window appears. This could be, for example, a notification shade that appears
6883 // after user starts to drag down on the launcher window.
6884 mDispatcher->onWindowInfosChanged(
6885 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6886 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6887 injectMotionEvent(*mDispatcher,
6888 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6889 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6890 .build()));
6891 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6892 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6893 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6894 injectMotionEvent(*mDispatcher,
6895 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6896 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6897 .build()));
6898 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6899
6900 originalWindow->assertNoEvents();
6901 appearingWindow->assertNoEvents();
6902}
6903
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006904TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006905 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006906 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6907
6908 sp<FakeWindowHandle> leftWindow =
6909 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6910 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006911 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006912
6913 sp<FakeWindowHandle> rightSpy =
6914 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6915 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006916 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006917 rightSpy->setSpy(true);
6918 rightSpy->setTrustedOverlay(true);
6919
6920 sp<FakeWindowHandle> rightWindow =
6921 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6922 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006923 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006924
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006925 mDispatcher->onWindowInfosChanged(
6926 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006927
6928 // Touch in the left window
6929 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6930 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6931 .build());
6932 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6933 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006934 ASSERT_NO_FATAL_FAILURE(
6935 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006936
6937 // Touch another finger over the right windows
6938 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6939 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6940 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6941 .build());
6942 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6943 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6944 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6945 mDispatcher->waitForIdle();
6946 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006947 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6948 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006949
6950 // Release finger over left window. The UP actions are not treated as device interaction.
6951 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6952 // is part of the UP action, we do not treat this as device interaction.
6953 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6954 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6955 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6956 .build());
6957 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6958 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6959 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6960 mDispatcher->waitForIdle();
6961 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6962
6963 // Move remaining finger
6964 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6965 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6966 .build());
6967 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6968 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6969 mDispatcher->waitForIdle();
6970 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006971 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006972
6973 // Release all fingers
6974 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6975 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6976 .build());
6977 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6978 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6979 mDispatcher->waitForIdle();
6980 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6981}
6982
6983TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6984 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6985
6986 sp<FakeWindowHandle> window =
6987 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6988 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006989 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006990
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006991 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006992 setFocusedWindow(window);
6993 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6994
6995 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6996 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6997 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006998 ASSERT_NO_FATAL_FAILURE(
6999 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007000
7001 // The UP actions are not treated as device interaction.
7002 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
7003 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
7004 mDispatcher->waitForIdle();
7005 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7006}
7007
Prabir Pradhan5893d362023-11-17 04:30:40 +00007008TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
7009 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7010
7011 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
7012 ADISPLAY_ID_DEFAULT);
7013 left->setFrame(Rect(0, 0, 100, 100));
7014 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
7015 "Right Window", ADISPLAY_ID_DEFAULT);
7016 right->setFrame(Rect(100, 0, 200, 100));
7017 sp<FakeWindowHandle> spy =
7018 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
7019 spy->setFrame(Rect(0, 0, 200, 100));
7020 spy->setTrustedOverlay(true);
7021 spy->setSpy(true);
7022
7023 mDispatcher->onWindowInfosChanged(
7024 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
7025
7026 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
7027 NotifyMotionArgs notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
7028 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
7029 mDispatcher->notifyMotion(notifyArgs);
7030
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007031 std::unique_ptr<MotionEvent> leftEnter = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00007032 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
7033 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007034 ASSERT_NE(nullptr, leftEnter);
Prabir Pradhan5893d362023-11-17 04:30:40 +00007035 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
7036 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007037 Not(WithEventId(leftEnter->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00007038 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
7039
7040 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
7041 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
7042 {PointF{150, 50}});
7043 mDispatcher->notifyMotion(notifyArgs);
7044
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007045 std::unique_ptr<MotionEvent> leftExit = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00007046 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
7047 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007048 ASSERT_NE(nullptr, leftExit);
Prabir Pradhan5893d362023-11-17 04:30:40 +00007049 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
7050 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007051 Not(WithEventId(leftExit->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00007052 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
7053
7054 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
7055}
7056
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00007057class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
7058protected:
7059 std::shared_ptr<FakeApplicationHandle> mApp;
7060 sp<FakeWindowHandle> mWindow;
7061
7062 virtual void SetUp() override {
7063 InputDispatcherTest::SetUp();
7064
7065 mApp = std::make_shared<FakeApplicationHandle>();
7066
7067 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
7068 mWindow->setFrame(Rect(0, 0, 100, 100));
7069
7070 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
7071 setFocusedWindow(mWindow);
7072 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
7073 }
7074
7075 void setFallback(int32_t keycode) {
7076 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
7077 return KeyEventBuilder(event).keyCode(keycode).build();
7078 });
7079 }
7080
7081 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007082 std::unique_ptr<KeyEvent> event = mWindow->consumeKey(handled);
7083 ASSERT_NE(nullptr, event);
7084 ASSERT_THAT(*event, matcher);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00007085 }
7086};
7087
7088TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
7089 mDispatcher->notifyKey(
7090 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7091 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
7092 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7093}
7094
7095TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
7096 mDispatcher->notifyKey(
7097 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7098 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
7099 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7100}
7101
7102TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
7103 mDispatcher->notifyKey(
7104 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7105
7106 // Do not handle this key event.
7107 consumeKey(/*handled=*/false,
7108 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7109 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7110
7111 // Since the policy did not request any fallback to be generated, ensure there are no events.
7112 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7113}
7114
7115TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
7116 setFallback(AKEYCODE_B);
7117 mDispatcher->notifyKey(
7118 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7119
7120 // Do not handle this key event.
7121 consumeKey(/*handled=*/false,
7122 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7123
7124 // Since the key was not handled, ensure the fallback event was dispatched instead.
7125 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7126 consumeKey(/*handled=*/true,
7127 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7128 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7129
7130 // Release the original key, and ensure the fallback key is also released.
7131 mDispatcher->notifyKey(
7132 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7133 consumeKey(/*handled=*/false,
7134 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7135 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7136 consumeKey(/*handled=*/true,
7137 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7138 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7139
7140 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7141 mWindow->assertNoEvents();
7142}
7143
7144TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
7145 setFallback(AKEYCODE_B);
7146 mDispatcher->notifyKey(
7147 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7148
7149 // Do not handle this key event, but handle the fallback.
7150 consumeKey(/*handled=*/false,
7151 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7152 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7153 consumeKey(/*handled=*/true,
7154 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7155 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7156
7157 // Release the original key, and ensure the fallback key is also released.
7158 mDispatcher->notifyKey(
7159 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7160 // But this time, the app handles the original key.
7161 consumeKey(/*handled=*/true,
7162 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7163 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7164 // Ensure the fallback key is canceled.
7165 consumeKey(/*handled=*/true,
7166 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7167 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7168
7169 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7170 mWindow->assertNoEvents();
7171}
7172
7173TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
7174 setFallback(AKEYCODE_B);
7175 mDispatcher->notifyKey(
7176 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7177
7178 // Do not handle this key event.
7179 consumeKey(/*handled=*/false,
7180 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7181 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7182 // App does not handle the fallback either, so ensure another fallback is not generated.
7183 setFallback(AKEYCODE_C);
7184 consumeKey(/*handled=*/false,
7185 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7186 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7187
7188 // Release the original key, and ensure the fallback key is also released.
7189 setFallback(AKEYCODE_B);
7190 mDispatcher->notifyKey(
7191 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7192 consumeKey(/*handled=*/false,
7193 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7194 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7195 consumeKey(/*handled=*/false,
7196 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7197 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7198
7199 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7200 mWindow->assertNoEvents();
7201}
7202
7203TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
7204 setFallback(AKEYCODE_B);
7205 mDispatcher->notifyKey(
7206 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7207
7208 // Do not handle this key event, so fallback is generated.
7209 consumeKey(/*handled=*/false,
7210 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7211 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7212 consumeKey(/*handled=*/true,
7213 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7214 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7215
7216 // Release the original key, but assume the policy is misbehaving and it
7217 // generates an inconsistent fallback to the one from the DOWN event.
7218 setFallback(AKEYCODE_C);
7219 mDispatcher->notifyKey(
7220 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7221 consumeKey(/*handled=*/false,
7222 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7223 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7224 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
7225 consumeKey(/*handled=*/true,
7226 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7227 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7228
7229 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7230 mWindow->assertNoEvents();
7231}
7232
7233TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
7234 setFallback(AKEYCODE_B);
7235 mDispatcher->notifyKey(
7236 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7237
7238 // Do not handle this key event, so fallback is generated.
7239 consumeKey(/*handled=*/false,
7240 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7241 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7242 consumeKey(/*handled=*/true,
7243 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7244 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7245
7246 // The original key is canceled.
7247 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
7248 .keyCode(AKEYCODE_A)
7249 .addFlag(AKEY_EVENT_FLAG_CANCELED)
7250 .build());
7251 consumeKey(/*handled=*/false,
7252 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
7253 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7254 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7255 // Ensure the fallback key is also canceled due to the original key being canceled.
7256 consumeKey(/*handled=*/true,
7257 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7258 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7259
7260 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7261 mWindow->assertNoEvents();
7262}
7263
Prabir Pradhanb13da8f2024-01-09 23:10:13 +00007264TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedDuringPolicyCall) {
7265 setFallback(AKEYCODE_B);
7266 mDispatcher->notifyKey(
7267 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7268
7269 // Do not handle this key event.
7270 consumeKey(/*handled=*/false,
7271 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7272 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7273 consumeKey(/*handled=*/true,
7274 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7275 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7276
7277 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
7278 // When the unhandled key is reported to the policy next, remove the input channel.
7279 mDispatcher->removeInputChannel(mWindow->getToken());
7280 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
7281 });
7282 // Release the original key, and let the app now handle the previously unhandled key.
7283 // This should result in the previously generated fallback key to be cancelled.
7284 // Since the policy was notified of the unhandled DOWN event earlier, it will also be notified
7285 // of the UP event for consistency. The Dispatcher calls into the policy from its own thread
7286 // without holding the lock, because it need to synchronously fetch the fallback key. While in
7287 // the policy call, we will now remove the input channel. Once the policy call returns, the
7288 // Dispatcher will no longer have a channel to send cancellation events to. Ensure this does
7289 // not cause any crashes.
7290 mDispatcher->notifyKey(
7291 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7292 consumeKey(/*handled=*/true,
7293 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7294 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7295}
7296
Garfield Tan1c7bc862020-01-28 13:24:04 -08007297class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
7298protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08007299 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
7300 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007301
Chris Yea209fde2020-07-22 13:54:51 -07007302 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007303 sp<FakeWindowHandle> mWindow;
7304
7305 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00007306 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00007307 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00007308 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09007309 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007310 ASSERT_EQ(OK, mDispatcher->start());
7311
7312 setUpWindow();
7313 }
7314
7315 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07007316 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007317 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007318
Vishnu Nair47074b82020-08-14 11:54:47 -07007319 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007320 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007321 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007322 mWindow->consumeFocusEvent(true);
7323 }
7324
Chris Ye2ad95392020-09-01 13:44:44 -07007325 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007326 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007327 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007328 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007329 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007330
7331 // Window should receive key down event.
7332 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7333 }
7334
7335 void expectKeyRepeatOnce(int32_t repeatCount) {
7336 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007337 mWindow->consumeKeyEvent(
7338 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007339 }
7340
Chris Ye2ad95392020-09-01 13:44:44 -07007341 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007342 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007343 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007344 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007345 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007346
7347 // Window should receive key down event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007348 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007349 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007350 }
7351};
7352
7353TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00007354 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007355 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7356 expectKeyRepeatOnce(repeatCount);
7357 }
7358}
7359
7360TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00007361 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007362 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7363 expectKeyRepeatOnce(repeatCount);
7364 }
Harry Cutts33476232023-01-30 19:57:29 +00007365 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007366 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08007367 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7368 expectKeyRepeatOnce(repeatCount);
7369 }
7370}
7371
7372TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007373 sendAndConsumeKeyDown(/*deviceId=*/1);
7374 expectKeyRepeatOnce(/*repeatCount=*/1);
7375 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007376 mWindow->assertNoEvents();
7377}
7378
7379TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007380 sendAndConsumeKeyDown(/*deviceId=*/1);
7381 expectKeyRepeatOnce(/*repeatCount=*/1);
7382 sendAndConsumeKeyDown(/*deviceId=*/2);
7383 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007384 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00007385 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007386 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00007387 expectKeyRepeatOnce(/*repeatCount=*/2);
7388 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07007389 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00007390 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007391 mWindow->assertNoEvents();
7392}
7393
7394TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007395 sendAndConsumeKeyDown(/*deviceId=*/1);
7396 expectKeyRepeatOnce(/*repeatCount=*/1);
7397 sendAndConsumeKeyDown(/*deviceId=*/2);
7398 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007399 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00007400 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007401 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08007402 mWindow->assertNoEvents();
7403}
7404
liushenxiang42232912021-05-21 20:24:09 +08007405TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
7406 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00007407 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007408 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08007409 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
7410 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
7411 mWindow->assertNoEvents();
7412}
7413
Garfield Tan1c7bc862020-01-28 13:24:04 -08007414TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007415 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007416 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007417 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007418 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
7419 ASSERT_NE(nullptr, repeatEvent);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007420 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007421 IdGenerator::getSource(repeatEvent->getId()));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007422 }
7423}
7424
7425TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007426 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007427 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007428
7429 std::unordered_set<int32_t> idSet;
7430 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007431 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
7432 ASSERT_NE(nullptr, repeatEvent);
7433 int32_t id = repeatEvent->getId();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007434 EXPECT_EQ(idSet.end(), idSet.find(id));
7435 idSet.insert(id);
7436 }
7437}
7438
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007439/* Test InputDispatcher for MultiDisplay */
7440class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
7441public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007442 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007443 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08007444
Chris Yea209fde2020-07-22 13:54:51 -07007445 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007446 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007447 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007448
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007449 // Set focus window for primary display, but focused display would be second one.
7450 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07007451 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007452 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
7453
Vishnu Nair958da932020-08-21 17:12:37 -07007454 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007455 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08007456
Chris Yea209fde2020-07-22 13:54:51 -07007457 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007458 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007459 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007460 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007461 // Set focus display to second one.
7462 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
7463 // Set focus window for second display.
7464 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07007465 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007466 mDispatcher->onWindowInfosChanged(
7467 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007468 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007469 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007470 }
7471
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007472 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007473 InputDispatcherTest::TearDown();
7474
Chris Yea209fde2020-07-22 13:54:51 -07007475 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007476 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07007477 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007478 windowInSecondary.clear();
7479 }
7480
7481protected:
Chris Yea209fde2020-07-22 13:54:51 -07007482 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007483 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07007484 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007485 sp<FakeWindowHandle> windowInSecondary;
7486};
7487
7488TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
7489 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007490 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007491 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007492 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007493 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08007494 windowInSecondary->assertNoEvents();
7495
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007496 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007497 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007498 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007499 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007500 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007501 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08007502}
7503
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007504TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08007505 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007506 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007507 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007508 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007509 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08007510 windowInSecondary->assertNoEvents();
7511
7512 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007513 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007514 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007515 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007516 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08007517
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007518 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007519 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08007520
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007521 // Old focus should receive a cancel event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007522 windowInSecondary->consumeKeyUp(ADISPLAY_ID_NONE, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08007523
7524 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007525 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08007526 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007527 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08007528 windowInSecondary->assertNoEvents();
7529}
7530
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007531// Test per-display input monitors for motion event.
7532TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08007533 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007534 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007535 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007536 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007537
7538 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007539 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007540 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007541 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007542 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007543 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007544 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007545 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007546
7547 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007548 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007549 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007550 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007551 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007552 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007553 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08007554 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007555
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007556 // Lift up the touch from the second display
7557 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007558 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007559 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7560 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
7561 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
7562
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007563 // Test inject a non-pointer motion event.
7564 // If specific a display, it will dispatch to the focused window of particular display,
7565 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007566 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007567 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007568 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007569 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007570 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007571 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007572 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007573}
7574
7575// Test per-display input monitors for key event.
7576TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007577 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08007578 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007579 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007580 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007581 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007582
7583 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007584 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007585 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007586 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007587 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007588 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007589 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007590}
7591
Vishnu Nair958da932020-08-21 17:12:37 -07007592TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
7593 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007594 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007595 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007596 mDispatcher->onWindowInfosChanged(
7597 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
7598 *windowInSecondary->getInfo()},
7599 {},
7600 0,
7601 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007602 setFocusedWindow(secondWindowInPrimary);
7603 windowInPrimary->consumeFocusEvent(false);
7604 secondWindowInPrimary->consumeFocusEvent(true);
7605
7606 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007607 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7608 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007609 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007610 windowInPrimary->assertNoEvents();
7611 windowInSecondary->assertNoEvents();
7612 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7613}
7614
Arthur Hungdfd528e2021-12-08 13:23:04 +00007615TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
7616 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007617 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007618 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007619 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007620
7621 // Test touch down on primary display.
7622 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007623 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007624 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7625 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7626 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
7627
7628 // Test touch down on second display.
7629 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007630 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007631 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7632 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
7633 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
7634
7635 // Trigger cancel touch.
7636 mDispatcher->cancelCurrentTouch();
7637 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7638 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7639 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
7640 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
7641
7642 // Test inject a move motion event, no window/monitor should receive the event.
7643 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007644 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007645 ADISPLAY_ID_DEFAULT, {110, 200}))
7646 << "Inject motion event should return InputEventInjectionResult::FAILED";
7647 windowInPrimary->assertNoEvents();
7648 monitorInPrimary.assertNoEvents();
7649
7650 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007651 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007652 SECOND_DISPLAY_ID, {110, 200}))
7653 << "Inject motion event should return InputEventInjectionResult::FAILED";
7654 windowInSecondary->assertNoEvents();
7655 monitorInSecondary.assertNoEvents();
7656}
7657
Hu Guocb134f12023-12-23 13:42:44 +00007658/**
7659 * Send a key to the primary display and to the secondary display.
7660 * Then cause the key on the primary display to be canceled by sending in a stale key.
7661 * Ensure that the key on the primary display is canceled, and that the key on the secondary display
7662 * does not get canceled.
7663 */
7664TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture) {
7665 // Send a key down on primary display
7666 mDispatcher->notifyKey(
7667 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7668 .displayId(ADISPLAY_ID_DEFAULT)
7669 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7670 .build());
7671 windowInPrimary->consumeKeyEvent(
7672 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7673 windowInSecondary->assertNoEvents();
7674
7675 // Send a key down on second display
7676 mDispatcher->notifyKey(
7677 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7678 .displayId(SECOND_DISPLAY_ID)
7679 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7680 .build());
7681 windowInSecondary->consumeKeyEvent(
7682 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7683 windowInPrimary->assertNoEvents();
7684
7685 // Send a valid key up event on primary display that will be dropped because it is stale
7686 NotifyKeyArgs staleKeyUp =
7687 KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
7688 .displayId(ADISPLAY_ID_DEFAULT)
7689 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7690 .build();
7691 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7692 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7693 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7694 mDispatcher->notifyKey(staleKeyUp);
7695
7696 // Only the key gesture corresponding to the dropped event should receive the cancel event.
7697 // Therefore, windowInPrimary should get the cancel event and windowInSecondary should not
7698 // receive any events.
7699 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
7700 WithDisplayId(ADISPLAY_ID_DEFAULT),
7701 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7702 windowInSecondary->assertNoEvents();
7703}
7704
7705/**
7706 * Similar to 'WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture' but for motion events.
7707 */
7708TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropMotionEvent_OnlyCancelCorrespondingGesture) {
7709 // Send touch down on primary display.
7710 mDispatcher->notifyMotion(
7711 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7712 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7713 .displayId(ADISPLAY_ID_DEFAULT)
7714 .build());
7715 windowInPrimary->consumeMotionEvent(
7716 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7717 windowInSecondary->assertNoEvents();
7718
7719 // Send touch down on second display.
7720 mDispatcher->notifyMotion(
7721 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7722 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7723 .displayId(SECOND_DISPLAY_ID)
7724 .build());
7725 windowInPrimary->assertNoEvents();
7726 windowInSecondary->consumeMotionEvent(
7727 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7728
7729 // inject a valid MotionEvent on primary display that will be stale when it arrives.
7730 NotifyMotionArgs staleMotionUp =
7731 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7732 .displayId(ADISPLAY_ID_DEFAULT)
7733 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7734 .build();
7735 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7736 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7737 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7738 mDispatcher->notifyMotion(staleMotionUp);
7739
7740 // For stale motion events, we let the gesture to complete. This behaviour is different from key
7741 // events, where we would cancel the current keys instead.
7742 windowInPrimary->consumeMotionEvent(WithMotionAction(ACTION_UP));
7743 windowInSecondary->assertNoEvents();
7744}
7745
Jackal Guof9696682018-10-05 12:23:23 +08007746class InputFilterTest : public InputDispatcherTest {
7747protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007748 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
7749 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08007750 NotifyMotionArgs motionArgs;
7751
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007752 motionArgs =
7753 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007754 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007755 motionArgs =
7756 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007757 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007758 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007759 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007760 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007761 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08007762 } else {
7763 mFakePolicy->assertFilterInputEventWasNotCalled();
7764 }
7765 }
7766
7767 void testNotifyKey(bool expectToBeFiltered) {
7768 NotifyKeyArgs keyArgs;
7769
7770 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007771 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007772 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007773 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007774 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007775
7776 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08007777 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007778 } else {
7779 mFakePolicy->assertFilterInputEventWasNotCalled();
7780 }
7781 }
7782};
7783
7784// Test InputFilter for MotionEvent
7785TEST_F(InputFilterTest, MotionEvent_InputFilter) {
7786 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007787 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7788 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007789
7790 // Enable InputFilter
7791 mDispatcher->setInputFilterEnabled(true);
7792 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007793 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
7794 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007795
7796 // Disable InputFilter
7797 mDispatcher->setInputFilterEnabled(false);
7798 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007799 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7800 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007801}
7802
7803// Test InputFilter for KeyEvent
7804TEST_F(InputFilterTest, KeyEvent_InputFilter) {
7805 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007806 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007807
7808 // Enable InputFilter
7809 mDispatcher->setInputFilterEnabled(true);
7810 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007811 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007812
7813 // Disable InputFilter
7814 mDispatcher->setInputFilterEnabled(false);
7815 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007816 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007817}
7818
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007819// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
7820// logical display coordinate space.
7821TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
7822 ui::Transform firstDisplayTransform;
7823 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7824 ui::Transform secondDisplayTransform;
7825 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
7826
7827 std::vector<gui::DisplayInfo> displayInfos(2);
7828 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
7829 displayInfos[0].transform = firstDisplayTransform;
7830 displayInfos[1].displayId = SECOND_DISPLAY_ID;
7831 displayInfos[1].transform = secondDisplayTransform;
7832
Patrick Williamsd828f302023-04-28 17:52:08 -05007833 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007834
7835 // Enable InputFilter
7836 mDispatcher->setInputFilterEnabled(true);
7837
7838 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007839 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
7840 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007841}
7842
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007843class InputFilterInjectionPolicyTest : public InputDispatcherTest {
7844protected:
7845 virtual void SetUp() override {
7846 InputDispatcherTest::SetUp();
7847
7848 /**
7849 * We don't need to enable input filter to test the injected event policy, but we enabled it
7850 * here to make the tests more realistic, since this policy only matters when inputfilter is
7851 * on.
7852 */
7853 mDispatcher->setInputFilterEnabled(true);
7854
7855 std::shared_ptr<InputApplicationHandle> application =
7856 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007857 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
7858 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007859
7860 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7861 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007862 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007863 setFocusedWindow(mWindow);
7864 mWindow->consumeFocusEvent(true);
7865 }
7866
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007867 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7868 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007869 KeyEvent event;
7870
7871 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7872 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
7873 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00007874 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007875 const int32_t additionalPolicyFlags =
7876 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
7877 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007878 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007879 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007880 policyFlags | additionalPolicyFlags));
7881
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007882 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007883 }
7884
7885 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7886 int32_t flags) {
7887 MotionEvent event;
7888 PointerProperties pointerProperties[1];
7889 PointerCoords pointerCoords[1];
7890 pointerProperties[0].clear();
7891 pointerProperties[0].id = 0;
7892 pointerCoords[0].clear();
7893 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
7894 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
7895
7896 ui::Transform identityTransform;
7897 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7898 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
7899 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
7900 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
7901 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07007902 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07007903 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007904 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007905
7906 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
7907 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007908 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007909 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007910 policyFlags | additionalPolicyFlags));
7911
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007912 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007913 }
7914
7915private:
7916 sp<FakeWindowHandle> mWindow;
7917};
7918
7919TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007920 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
7921 // filter. Without it, the event will no different from a regularly injected event, and the
7922 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00007923 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
7924 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007925}
7926
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007927TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007928 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007929 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007930 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
7931}
7932
7933TEST_F(InputFilterInjectionPolicyTest,
7934 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
7935 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007936 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007937 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007938}
7939
7940TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00007941 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
7942 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007943}
7944
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08007945class InputDispatcherUserActivityPokeTests : public InputDispatcherTest {
7946protected:
7947 virtual void SetUp() override {
7948 InputDispatcherTest::SetUp();
7949
7950 std::shared_ptr<FakeApplicationHandle> application =
7951 std::make_shared<FakeApplicationHandle>();
7952 application->setDispatchingTimeout(100ms);
7953 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
7954 ADISPLAY_ID_DEFAULT);
Yeabkal Wubshit222d83d2024-01-24 18:00:09 +00007955 mWindow->setFrame(Rect(0, 0, 100, 100));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08007956 mWindow->setDispatchingTimeout(100ms);
7957 mWindow->setFocusable(true);
7958
7959 // Set focused application.
7960 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7961
7962 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
7963 setFocusedWindow(mWindow);
7964 mWindow->consumeFocusEvent(true);
7965 }
7966
7967 void notifyAndConsumeMotion(int32_t action, uint32_t source, int32_t displayId,
7968 nsecs_t eventTime) {
7969 mDispatcher->notifyMotion(MotionArgsBuilder(action, source)
7970 .displayId(displayId)
7971 .eventTime(eventTime)
7972 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7973 .build());
7974 mWindow->consumeMotionEvent(WithMotionAction(action));
7975 }
7976
7977private:
7978 sp<FakeWindowHandle> mWindow;
7979};
7980
7981TEST_F_WITH_FLAGS(
7982 InputDispatcherUserActivityPokeTests, MinPokeTimeObserved,
7983 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
7984 rate_limit_user_activity_poke_in_dispatcher))) {
7985 mDispatcher->setMinTimeBetweenUserActivityPokes(50ms);
7986
7987 // First event of type TOUCH. Should poke.
7988 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7989 milliseconds_to_nanoseconds(50));
7990 mFakePolicy->assertUserActivityPoked(
7991 {{milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
7992
7993 // 80ns > 50ns has passed since previous TOUCH event. Should poke.
7994 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7995 milliseconds_to_nanoseconds(130));
7996 mFakePolicy->assertUserActivityPoked(
7997 {{milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
7998
7999 // First event of type OTHER. Should poke (despite being within 50ns of previous TOUCH event).
8000 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8001 milliseconds_to_nanoseconds(135));
8002 mFakePolicy->assertUserActivityPoked(
8003 {{milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER, ADISPLAY_ID_DEFAULT}});
8004
8005 // Within 50ns of previous TOUCH event. Should NOT poke.
8006 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8007 milliseconds_to_nanoseconds(140));
8008 mFakePolicy->assertUserActivityNotPoked();
8009
8010 // Within 50ns of previous OTHER event. Should NOT poke.
8011 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8012 milliseconds_to_nanoseconds(150));
8013 mFakePolicy->assertUserActivityNotPoked();
8014
8015 // Within 50ns of previous TOUCH event (which was at time 130). Should NOT poke.
8016 // Note that STYLUS is mapped to TOUCH user activity, since it's a pointer-type source.
8017 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
8018 milliseconds_to_nanoseconds(160));
8019 mFakePolicy->assertUserActivityNotPoked();
8020
8021 // 65ns > 50ns has passed since previous OTHER event. Should poke.
8022 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8023 milliseconds_to_nanoseconds(200));
8024 mFakePolicy->assertUserActivityPoked(
8025 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER, ADISPLAY_ID_DEFAULT}});
8026
8027 // 170ns > 50ns has passed since previous TOUCH event. Should poke.
8028 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
8029 milliseconds_to_nanoseconds(300));
8030 mFakePolicy->assertUserActivityPoked(
8031 {{milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8032
8033 // Assert that there's no more user activity poke event.
8034 mFakePolicy->assertUserActivityNotPoked();
8035}
8036
8037TEST_F_WITH_FLAGS(
8038 InputDispatcherUserActivityPokeTests, DefaultMinPokeTimeOf100MsUsed,
8039 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8040 rate_limit_user_activity_poke_in_dispatcher))) {
8041 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8042 milliseconds_to_nanoseconds(200));
8043 mFakePolicy->assertUserActivityPoked(
8044 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8045
8046 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8047 milliseconds_to_nanoseconds(280));
8048 mFakePolicy->assertUserActivityNotPoked();
8049
8050 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8051 milliseconds_to_nanoseconds(340));
8052 mFakePolicy->assertUserActivityPoked(
8053 {{milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8054}
8055
8056TEST_F_WITH_FLAGS(
8057 InputDispatcherUserActivityPokeTests, ZeroMinPokeTimeDisablesRateLimiting,
8058 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8059 rate_limit_user_activity_poke_in_dispatcher))) {
8060 mDispatcher->setMinTimeBetweenUserActivityPokes(0ms);
8061
8062 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20);
8063 mFakePolicy->assertUserActivityPoked();
8064
8065 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 30);
8066 mFakePolicy->assertUserActivityPoked();
8067}
8068
chaviwfd6d3512019-03-25 13:23:49 -07008069class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008070 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07008071 InputDispatcherTest::SetUp();
8072
Chris Yea209fde2020-07-22 13:54:51 -07008073 std::shared_ptr<FakeApplicationHandle> application =
8074 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008075 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008076 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07008077 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07008078
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008079 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008080 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008081 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07008082
8083 // Set focused application.
8084 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07008085 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07008086
8087 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008088 mDispatcher->onWindowInfosChanged(
8089 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008090 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008091 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07008092 }
8093
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008094 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07008095 InputDispatcherTest::TearDown();
8096
8097 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008098 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07008099 }
8100
8101protected:
8102 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008103 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008104 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07008105};
8106
8107// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
8108// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
8109// the onPointerDownOutsideFocus callback.
8110TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008111 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008112 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008113 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008114 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008115 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008116
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008117 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07008118 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
8119}
8120
8121// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
8122// DOWN on the window that doesn't have focus. Ensure no window received the
8123// onPointerDownOutsideFocus callback.
8124TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008125 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008126 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
8127 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008128 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008129 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008130
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008131 ASSERT_TRUE(mDispatcher->waitForIdle());
8132 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008133}
8134
8135// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
8136// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
8137TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08008138 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008139 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008140 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008141 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07008142
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008143 ASSERT_TRUE(mDispatcher->waitForIdle());
8144 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008145}
8146
8147// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
8148// DOWN on the window that already has focus. Ensure no window received the
8149// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008150TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008151 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008152 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008153 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008154 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008155 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008156
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008157 ASSERT_TRUE(mDispatcher->waitForIdle());
8158 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008159}
8160
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008161// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
8162// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
8163TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
8164 const MotionEvent event =
8165 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
8166 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008167 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008168 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
8169 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008170 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008171 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8172 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
8173
8174 ASSERT_TRUE(mDispatcher->waitForIdle());
8175 mFakePolicy->assertOnPointerDownWasNotCalled();
8176 // Ensure that the unfocused window did not receive any FOCUS events.
8177 mUnfocusedWindow->assertNoEvents();
8178}
8179
chaviwaf87b3e2019-10-01 16:59:28 -07008180// These tests ensures we can send touch events to a single client when there are multiple input
8181// windows that point to the same client token.
8182class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
8183 virtual void SetUp() override {
8184 InputDispatcherTest::SetUp();
8185
Chris Yea209fde2020-07-22 13:54:51 -07008186 std::shared_ptr<FakeApplicationHandle> application =
8187 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008188 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
8189 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07008190 mWindow1->setFrame(Rect(0, 0, 100, 100));
8191
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00008192 mWindow2 = mWindow1->clone(ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07008193 mWindow2->setFrame(Rect(100, 100, 200, 200));
8194
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008195 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07008196 }
8197
8198protected:
8199 sp<FakeWindowHandle> mWindow1;
8200 sp<FakeWindowHandle> mWindow2;
8201
8202 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05008203 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07008204 vec2 vals = windowInfo->transform.transform(point.x, point.y);
8205 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07008206 }
8207
8208 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
8209 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008210 const std::string name = window->getName();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008211 std::unique_ptr<MotionEvent> motionEvent =
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008212 window->consumeMotionEvent(WithMotionAction(expectedAction));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008213 ASSERT_NE(nullptr, motionEvent);
8214 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07008215
8216 for (size_t i = 0; i < points.size(); i++) {
8217 float expectedX = points[i].x;
8218 float expectedY = points[i].y;
8219
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008220 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07008221 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008222 << ", got " << motionEvent->getX(i);
8223 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07008224 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008225 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07008226 }
8227 }
chaviw9eaa22c2020-07-01 16:21:27 -07008228
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08008229 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07008230 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008231 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
8232 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07008233
8234 // Always consume from window1 since it's the window that has the InputReceiver
8235 consumeMotionEvent(mWindow1, action, expectedPoints);
8236 }
chaviwaf87b3e2019-10-01 16:59:28 -07008237};
8238
8239TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
8240 // Touch Window 1
8241 PointF touchedPoint = {10, 10};
8242 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07008243 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008244
8245 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07008246 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008247
8248 // Touch Window 2
8249 touchedPoint = {150, 150};
8250 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07008251 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008252}
8253
chaviw9eaa22c2020-07-01 16:21:27 -07008254TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
8255 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07008256 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008257 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07008258
8259 // Touch Window 1
8260 PointF touchedPoint = {10, 10};
8261 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07008262 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008263 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07008264 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008265
8266 // Touch Window 2
8267 touchedPoint = {150, 150};
8268 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07008269 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
8270 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008271
chaviw9eaa22c2020-07-01 16:21:27 -07008272 // Update the transform so rotation is set
8273 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008274 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008275 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
8276 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008277}
8278
chaviw9eaa22c2020-07-01 16:21:27 -07008279TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008280 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008281 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008282
8283 // Touch Window 1
8284 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8285 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07008286 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008287
8288 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07008289 touchedPoints.push_back(PointF{150, 150});
8290 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08008291 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008292
chaviw9eaa22c2020-07-01 16:21:27 -07008293 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08008294 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008295 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008296
chaviw9eaa22c2020-07-01 16:21:27 -07008297 // Update the transform so rotation is set for Window 2
8298 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008299 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008300 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08008301 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008302}
8303
chaviw9eaa22c2020-07-01 16:21:27 -07008304TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008305 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008306 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008307
8308 // Touch Window 1
8309 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8310 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07008311 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008312
8313 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07008314 touchedPoints.push_back(PointF{150, 150});
8315 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008316
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08008317 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008318
8319 // Move both windows
8320 touchedPoints = {{20, 20}, {175, 175}};
8321 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8322 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8323
chaviw9eaa22c2020-07-01 16:21:27 -07008324 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008325
chaviw9eaa22c2020-07-01 16:21:27 -07008326 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08008327 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008328 expectedPoints.pop_back();
8329
8330 // Touch Window 2
8331 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008332 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008333 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08008334 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008335
8336 // Move both windows
8337 touchedPoints = {{20, 20}, {175, 175}};
8338 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8339 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8340
8341 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008342}
8343
8344TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
8345 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008346 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008347
8348 // Touch Window 1
8349 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8350 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07008351 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008352
8353 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07008354 touchedPoints.push_back(PointF{150, 150});
8355 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008356
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08008357 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008358
8359 // Move both windows
8360 touchedPoints = {{20, 20}, {175, 175}};
8361 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8362 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8363
chaviw9eaa22c2020-07-01 16:21:27 -07008364 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008365}
8366
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07008367/**
8368 * When one of the windows is slippery, the touch should not slip into the other window with the
8369 * same input channel.
8370 */
8371TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
8372 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008373 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07008374
8375 // Touch down in window 1
8376 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8377 ADISPLAY_ID_DEFAULT, {{50, 50}}));
8378 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
8379
8380 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
8381 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
8382 // getting generated.
8383 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8384 ADISPLAY_ID_DEFAULT, {{150, 150}}));
8385
8386 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
8387}
8388
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008389/**
8390 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
8391 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
8392 * that the pointer is hovering over may have a different transform.
8393 */
8394TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008395 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008396
8397 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008398 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
8399 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8400 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008401 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
8402 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008403 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008404 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8405 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
8406 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008407 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
8408 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
8409 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
8410}
8411
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008412class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
8413 virtual void SetUp() override {
8414 InputDispatcherTest::SetUp();
8415
Chris Yea209fde2020-07-22 13:54:51 -07008416 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008417 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008418 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
8419 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008420 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008421 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07008422 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008423
8424 // Set focused application.
8425 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8426
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008427 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008428 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008429 mWindow->consumeFocusEvent(true);
8430 }
8431
8432 virtual void TearDown() override {
8433 InputDispatcherTest::TearDown();
8434 mWindow.clear();
8435 }
8436
8437protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008438 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07008439 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008440 sp<FakeWindowHandle> mWindow;
8441 static constexpr PointF WINDOW_LOCATION = {20, 20};
8442
8443 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008444 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
8445 .x(WINDOW_LOCATION.x)
8446 .y(WINDOW_LOCATION.y);
8447 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8448 .pointer(touchingPointer)
8449 .build());
8450 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8451 .pointer(touchingPointer)
8452 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008453 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008454
8455 sp<FakeWindowHandle> addSpyWindow() {
8456 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008457 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008458 spy->setTrustedOverlay(true);
8459 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008460 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008461 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008462 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008463 return spy;
8464 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008465};
8466
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008467// Send a tap and respond, which should not cause an ANR.
8468TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
8469 tapOnWindow();
8470 mWindow->consumeMotionDown();
8471 mWindow->consumeMotionUp();
8472 ASSERT_TRUE(mDispatcher->waitForIdle());
8473 mFakePolicy->assertNotifyAnrWasNotCalled();
8474}
8475
8476// Send a regular key and respond, which should not cause an ANR.
8477TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008478 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008479 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8480 ASSERT_TRUE(mDispatcher->waitForIdle());
8481 mFakePolicy->assertNotifyAnrWasNotCalled();
8482}
8483
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008484TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
8485 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008486 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008487 mWindow->consumeFocusEvent(false);
8488
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008489 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008490 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8491 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00008492 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008493 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008494 // Key will not go to window because we have no focused window.
8495 // The 'no focused window' ANR timer should start instead.
8496
8497 // Now, the focused application goes away.
8498 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
8499 // The key should get dropped and there should be no ANR.
8500
8501 ASSERT_TRUE(mDispatcher->waitForIdle());
8502 mFakePolicy->assertNotifyAnrWasNotCalled();
8503}
8504
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008505// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008506// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8507// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008508TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008509 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008510 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008511 WINDOW_LOCATION));
8512
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008513 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008514 ASSERT_TRUE(sequenceNum);
8515 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008516 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008517
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008518 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008519 mWindow->consumeMotionEvent(
8520 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008521 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008522 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008523}
8524
8525// Send a key to the app and have the app not respond right away.
8526TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
8527 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008528 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008529 const auto [sequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008530 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008531 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008532 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008533 ASSERT_TRUE(mDispatcher->waitForIdle());
8534}
8535
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008536// We have a focused application, but no focused window
8537TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008538 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008539 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008540 mWindow->consumeFocusEvent(false);
8541
8542 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008543 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008544 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008545 WINDOW_LOCATION));
8546 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
8547 mDispatcher->waitForIdle();
8548 mFakePolicy->assertNotifyAnrWasNotCalled();
8549
8550 // Once a focused event arrives, we get an ANR for this application
8551 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8552 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008553 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008554 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008555 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008556 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008557 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07008558 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008559 ASSERT_TRUE(mDispatcher->waitForIdle());
8560}
8561
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008562/**
8563 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
8564 * there will not be an ANR.
8565 */
8566TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
8567 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008568 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008569 mWindow->consumeFocusEvent(false);
8570
8571 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07008572 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
8573 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008574 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
8575 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
8576
8577 // Define a valid key down event that is stale (too old).
8578 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00008579 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00008580 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008581
8582 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
8583
8584 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00008585 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008586 InputEventInjectionSync::WAIT_FOR_RESULT,
8587 INJECT_EVENT_TIMEOUT, policyFlags);
8588 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
8589 << "Injection should fail because the event is stale";
8590
8591 ASSERT_TRUE(mDispatcher->waitForIdle());
8592 mFakePolicy->assertNotifyAnrWasNotCalled();
8593 mWindow->assertNoEvents();
8594}
8595
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008596// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008597// Make sure that we don't notify policy twice about the same ANR.
8598TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008599 const std::chrono::duration appTimeout = 400ms;
8600 mApplication->setDispatchingTimeout(appTimeout);
8601 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8602
Vishnu Nair47074b82020-08-14 11:54:47 -07008603 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008604 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008605 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008606
8607 // Once a focused event arrives, we get an ANR for this application
8608 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8609 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008610 const std::chrono::duration eventInjectionTimeout = 100ms;
8611 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008612 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008613 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008614 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
8615 /*allowKeyRepeat=*/false);
8616 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
8617 << "result=" << ftl::enum_string(result);
8618 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
8619 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
8620 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
8621 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008622
Vishnu Naire4df8752022-09-08 09:17:55 -07008623 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008624 // ANR should not be raised again. It is up to policy to do that if it desires.
8625 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008626
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008627 // If we now get a focused window, the ANR should stop, but the policy handles that via
8628 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008629 ASSERT_TRUE(mDispatcher->waitForIdle());
8630}
8631
8632// We have a focused application, but no focused window
8633TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008634 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008635 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008636 mWindow->consumeFocusEvent(false);
8637
8638 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008639 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008640
Vishnu Naire4df8752022-09-08 09:17:55 -07008641 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8642 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008643
8644 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008645 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008646 ASSERT_TRUE(mDispatcher->waitForIdle());
8647 mWindow->assertNoEvents();
8648}
8649
8650/**
8651 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
8652 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
8653 * If we process 1 of the events, but ANR on the second event with the same timestamp,
8654 * the ANR mechanism should still work.
8655 *
8656 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
8657 * DOWN event, while not responding on the second one.
8658 */
8659TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
8660 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008661 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008662 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8663 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8664 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008665 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008666
8667 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008668 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008669 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8670 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8671 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008672 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008673
8674 // We have now sent down and up. Let's consume first event and then ANR on the second.
8675 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8676 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008677 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008678}
8679
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008680// A spy window can receive an ANR
8681TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
8682 sp<FakeWindowHandle> spy = addSpyWindow();
8683
8684 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008685 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008686 WINDOW_LOCATION));
8687 mWindow->consumeMotionDown();
8688
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008689 const auto [sequenceNum, _] = spy->receiveEvent(); // ACTION_DOWN
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008690 ASSERT_TRUE(sequenceNum);
8691 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008692 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008693
8694 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008695 spy->consumeMotionEvent(
8696 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008697 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008698 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008699}
8700
8701// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008702// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008703TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
8704 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008705
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008706 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008707 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008708 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008709 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008710
8711 // Stuck on the ACTION_UP
8712 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008713 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008714
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008715 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008716 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008717 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8718 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008719
8720 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8721 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008722 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008723 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008724 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008725}
8726
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008727// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008728// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008729TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
8730 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008731
8732 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008733 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8734 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008735
8736 mWindow->consumeMotionDown();
8737 // Stuck on the ACTION_UP
8738 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008739 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008740
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008741 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008742 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008743 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8744 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008745
8746 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8747 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008748 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008749 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008750 spy->assertNoEvents();
8751}
8752
8753TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008754 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008755
Prabir Pradhanfb549072023-10-05 19:17:36 +00008756 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008757
8758 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008759 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008760 WINDOW_LOCATION));
8761
8762 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8763 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
8764 ASSERT_TRUE(consumeSeq);
8765
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008766 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
8767 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008768
8769 monitor.finishEvent(*consumeSeq);
8770 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
8771
8772 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008773 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008774}
8775
8776// If a window is unresponsive, then you get anr. if the window later catches up and starts to
8777// process events, you don't get an anr. When the window later becomes unresponsive again, you
8778// get an ANR again.
8779// 1. tap -> block on ACTION_UP -> receive ANR
8780// 2. consume all pending events (= queue becomes healthy again)
8781// 3. tap again -> block on ACTION_UP again -> receive ANR second time
8782TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
8783 tapOnWindow();
8784
8785 mWindow->consumeMotionDown();
8786 // Block on ACTION_UP
8787 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008788 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008789 mWindow->consumeMotionUp(); // Now the connection should be healthy again
8790 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008791 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008792 mWindow->assertNoEvents();
8793
8794 tapOnWindow();
8795 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008796 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008797 mWindow->consumeMotionUp();
8798
8799 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008800 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008801 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008802 mWindow->assertNoEvents();
8803}
8804
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008805// If a connection remains unresponsive for a while, make sure policy is only notified once about
8806// it.
8807TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008808 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008809 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008810 WINDOW_LOCATION));
8811
8812 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008813 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008814 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008815 // 'notifyConnectionUnresponsive' should only be called once per connection
8816 mFakePolicy->assertNotifyAnrWasNotCalled();
8817 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008818 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008819 mWindow->consumeMotionEvent(
8820 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008821 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008822 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008823 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008824 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008825}
8826
8827/**
8828 * 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 -07008829 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008830 *
8831 * Warning!!!
8832 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8833 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008834 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008835 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8836 *
8837 * If that value changes, this test should also change.
8838 */
8839TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
8840 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008841 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008842
8843 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008844 const auto& [downSequenceNum, downEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008845 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008846 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008847 ASSERT_TRUE(upSequenceNum);
8848 // Don't finish the events yet, and send a key
8849 // Injection will "succeed" because we will eventually give up and send the key to the focused
8850 // window even if motions are still being processed. But because the injection timeout is short,
8851 // we will receive INJECTION_TIMED_OUT as the result.
8852
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008853 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008854 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8855 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008856 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008857 // Key will not be sent to the window, yet, because the window is still processing events
8858 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008859 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
8860 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8861 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8862 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008863
8864 std::this_thread::sleep_for(500ms);
8865 // if we wait long enough though, dispatcher will give up, and still send the key
8866 // to the focused window, even though we have not yet finished the motion event
8867 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8868 mWindow->finishEvent(*downSequenceNum);
8869 mWindow->finishEvent(*upSequenceNum);
8870}
8871
8872/**
8873 * If a window is processing a motion event, and then a key event comes in, the key event should
8874 * not go to the focused window until the motion is processed.
8875 * If then a new motion comes in, then the pending key event should be going to the currently
8876 * focused window right away.
8877 */
8878TEST_F(InputDispatcherSingleWindowAnr,
8879 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
8880 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008881 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008882
8883 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008884 const auto& [downSequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008885 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008886 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008887 ASSERT_TRUE(upSequenceNum);
8888 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008889 mDispatcher->notifyKey(
8890 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
8891 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8892 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008893 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008894 // Make sure the `assertNoEvents` check doesn't take too long. It uses
8895 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8896 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8897 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008898
8899 // Now tap down again. It should cause the pending key to go to the focused window right away.
8900 tapOnWindow();
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008901 mWindow->consumeKeyEvent(WithKeyAction(AKEY_EVENT_ACTION_DOWN)); // it doesn't matter that we
8902 // haven't ack'd the other events yet. We can finish events in any order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008903 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
8904 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008905 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8906 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008907 mWindow->assertNoEvents();
8908}
8909
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07008910/**
8911 * Send an event to the app and have the app not respond right away.
8912 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8913 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
8914 * At some point, the window becomes responsive again.
8915 * Ensure that subsequent events get dropped, and the next gesture is delivered.
8916 */
8917TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
8918 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8919 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
8920 .build());
8921
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008922 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07008923 ASSERT_TRUE(sequenceNum);
8924 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8925 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
8926
8927 mWindow->finishEvent(*sequenceNum);
8928 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
8929 ASSERT_TRUE(mDispatcher->waitForIdle());
8930 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
8931
8932 // Now that the window is responsive, let's continue the gesture.
8933 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8934 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8935 .build());
8936
8937 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8938 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8939 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8940 .build());
8941
8942 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8943 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8944 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8945 .build());
8946 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8947 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8948 .build());
8949 // We already canceled this pointer, so the window shouldn't get any new events.
8950 mWindow->assertNoEvents();
8951
8952 // Start another one.
8953 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8954 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
8955 .build());
8956 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8957}
8958
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008959class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
8960 virtual void SetUp() override {
8961 InputDispatcherTest::SetUp();
8962
Chris Yea209fde2020-07-22 13:54:51 -07008963 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008964 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008965 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
8966 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008967 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008968 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008969 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008970
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008971 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
8972 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008973 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008974 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008975
8976 // Set focused application.
8977 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07008978 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008979
8980 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008981 mDispatcher->onWindowInfosChanged(
8982 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008983 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008984 mFocusedWindow->consumeFocusEvent(true);
8985 }
8986
8987 virtual void TearDown() override {
8988 InputDispatcherTest::TearDown();
8989
8990 mUnfocusedWindow.clear();
8991 mFocusedWindow.clear();
8992 }
8993
8994protected:
Chris Yea209fde2020-07-22 13:54:51 -07008995 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008996 sp<FakeWindowHandle> mUnfocusedWindow;
8997 sp<FakeWindowHandle> mFocusedWindow;
8998 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
8999 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
9000 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
9001
9002 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
9003
9004 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
9005
9006private:
9007 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009008 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009009 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009010 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009011 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009012 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009013 location));
9014 }
9015};
9016
9017// If we have 2 windows that are both unresponsive, the one with the shortest timeout
9018// should be ANR'd first.
9019TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009020 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009021 injectMotionEvent(*mDispatcher,
9022 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9023 AINPUT_SOURCE_TOUCHSCREEN)
9024 .pointer(PointerBuilder(0, ToolType::FINGER)
9025 .x(FOCUSED_WINDOW_LOCATION.x)
9026 .y(FOCUSED_WINDOW_LOCATION.y))
9027 .build()));
9028 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9029 injectMotionEvent(*mDispatcher,
9030 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
9031 AINPUT_SOURCE_TOUCHSCREEN)
9032 .pointer(PointerBuilder(0, ToolType::FINGER)
9033 .x(FOCUSED_WINDOW_LOCATION.x)
9034 .y(FOCUSED_WINDOW_LOCATION.y))
9035 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009036 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009037 mFocusedWindow->consumeMotionUp();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009038 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009039 // We consumed all events, so no ANR
9040 ASSERT_TRUE(mDispatcher->waitForIdle());
9041 mFakePolicy->assertNotifyAnrWasNotCalled();
9042
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009043 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009044 injectMotionEvent(*mDispatcher,
9045 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9046 AINPUT_SOURCE_TOUCHSCREEN)
9047 .pointer(PointerBuilder(0, ToolType::FINGER)
9048 .x(FOCUSED_WINDOW_LOCATION.x)
9049 .y(FOCUSED_WINDOW_LOCATION.y))
9050 .build()));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009051 const auto [unfocusedSequenceNum, _] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009052 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009053
9054 const std::chrono::duration timeout =
9055 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009056 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009057
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009058 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009059 mFocusedWindow->consumeMotionDown();
9060 // This cancel is generated because the connection was unresponsive
9061 mFocusedWindow->consumeMotionCancel();
9062 mFocusedWindow->assertNoEvents();
9063 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009064 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009065 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9066 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009067 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009068}
9069
9070// If we have 2 windows with identical timeouts that are both unresponsive,
9071// it doesn't matter which order they should have ANR.
9072// But we should receive ANR for both.
9073TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
9074 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009075 mUnfocusedWindow->setDispatchingTimeout(
9076 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009077 mDispatcher->onWindowInfosChanged(
9078 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009079
9080 tapOnFocusedWindow();
9081 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009082 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009083 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
9084 mFocusedWindow->getDispatchingTimeout(
9085 DISPATCHING_TIMEOUT)),
9086 mFakePolicy->getUnresponsiveWindowToken(0ms)};
9087
9088 ASSERT_THAT(anrConnectionTokens,
9089 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
9090 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009091
9092 ASSERT_TRUE(mDispatcher->waitForIdle());
9093 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009094
9095 mFocusedWindow->consumeMotionDown();
9096 mFocusedWindow->consumeMotionUp();
9097 mUnfocusedWindow->consumeMotionOutside();
9098
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009099 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
9100 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009101
9102 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009103 ASSERT_THAT(responsiveTokens,
9104 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
9105 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009106 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009107}
9108
9109// If a window is already not responding, the second tap on the same window should be ignored.
9110// We should also log an error to account for the dropped event (not tested here).
9111// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
9112TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
9113 tapOnFocusedWindow();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009114 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009115 // Receive the events, but don't respond
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009116 const auto [downEventSequenceNum, downEvent] = mFocusedWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009117 ASSERT_TRUE(downEventSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009118 const auto [upEventSequenceNum, upEvent] = mFocusedWindow->receiveEvent(); // ACTION_UP
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009119 ASSERT_TRUE(upEventSequenceNum);
9120 const std::chrono::duration timeout =
9121 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009122 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009123
9124 // Tap once again
9125 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009126 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009127 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009128 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009129 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009130 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009131 FOCUSED_WINDOW_LOCATION));
9132 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
9133 // valid touch target
9134 mUnfocusedWindow->assertNoEvents();
9135
9136 // Consume the first tap
9137 mFocusedWindow->finishEvent(*downEventSequenceNum);
9138 mFocusedWindow->finishEvent(*upEventSequenceNum);
9139 ASSERT_TRUE(mDispatcher->waitForIdle());
9140 // The second tap did not go to the focused window
9141 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009142 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08009143 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9144 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009145 mFakePolicy->assertNotifyAnrWasNotCalled();
9146}
9147
9148// If you tap outside of all windows, there will not be ANR
9149TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009150 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009151 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009152 LOCATION_OUTSIDE_ALL_WINDOWS));
9153 ASSERT_TRUE(mDispatcher->waitForIdle());
9154 mFakePolicy->assertNotifyAnrWasNotCalled();
9155}
9156
9157// Since the focused window is paused, tapping on it should not produce any events
9158TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
9159 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009160 mDispatcher->onWindowInfosChanged(
9161 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009162
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009163 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009164 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009165 FOCUSED_WINDOW_LOCATION));
9166
9167 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
9168 ASSERT_TRUE(mDispatcher->waitForIdle());
9169 // Should not ANR because the window is paused, and touches shouldn't go to it
9170 mFakePolicy->assertNotifyAnrWasNotCalled();
9171
9172 mFocusedWindow->assertNoEvents();
9173 mUnfocusedWindow->assertNoEvents();
9174}
9175
9176/**
9177 * 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 -07009178 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009179 * If a different window becomes focused at this time, the key should go to that window instead.
9180 *
9181 * Warning!!!
9182 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
9183 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009184 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009185 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
9186 *
9187 * If that value changes, this test should also change.
9188 */
9189TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
9190 // Set a long ANR timeout to prevent it from triggering
9191 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009192 mDispatcher->onWindowInfosChanged(
9193 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009194
9195 tapOnUnfocusedWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009196 const auto [downSequenceNum, downEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009197 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009198 const auto [upSequenceNum, upEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009199 ASSERT_TRUE(upSequenceNum);
9200 // Don't finish the events yet, and send a key
9201 // Injection will succeed because we will eventually give up and send the key to the focused
9202 // window even if motions are still being processed.
9203
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009204 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009205 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9206 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009207 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009208 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009209 // and the key remains pending, waiting for the touch events to be processed.
9210 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
9211 // under the hood.
9212 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
9213 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009214
9215 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07009216 mFocusedWindow->setFocusable(false);
9217 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009218 mDispatcher->onWindowInfosChanged(
9219 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009220 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009221
9222 // Focus events should precede the key events
9223 mUnfocusedWindow->consumeFocusEvent(true);
9224 mFocusedWindow->consumeFocusEvent(false);
9225
9226 // Finish the tap events, which should unblock dispatcher
9227 mUnfocusedWindow->finishEvent(*downSequenceNum);
9228 mUnfocusedWindow->finishEvent(*upSequenceNum);
9229
9230 // Now that all queues are cleared and no backlog in the connections, the key event
9231 // can finally go to the newly focused "mUnfocusedWindow".
9232 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9233 mFocusedWindow->assertNoEvents();
9234 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009235 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009236}
9237
9238// When the touch stream is split across 2 windows, and one of them does not respond,
9239// then ANR should be raised and the touch should be canceled for the unresponsive window.
9240// The other window should not be affected by that.
9241TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
9242 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00009243 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9244 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9245 {FOCUSED_WINDOW_LOCATION}));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009246 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009247
9248 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00009249 mDispatcher->notifyMotion(
9250 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9251 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009252
9253 const std::chrono::duration timeout =
9254 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009255 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009256
9257 mUnfocusedWindow->consumeMotionDown();
9258 mFocusedWindow->consumeMotionDown();
9259 // Focused window may or may not receive ACTION_MOVE
9260 // But it should definitely receive ACTION_CANCEL due to the ANR
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009261 const auto [moveOrCancelSequenceNum, event] = mFocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009262 ASSERT_TRUE(moveOrCancelSequenceNum);
9263 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
9264 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009265 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009266 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
9267 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
9268 mFocusedWindow->consumeMotionCancel();
9269 } else {
9270 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
9271 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009272 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009273 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9274 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009275
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009276 mUnfocusedWindow->assertNoEvents();
9277 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009278 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009279}
9280
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009281/**
9282 * If we have no focused window, and a key comes in, we start the ANR timer.
9283 * The focused application should add a focused window before the timer runs out to prevent ANR.
9284 *
9285 * If the user touches another application during this time, the key should be dropped.
9286 * Next, if a new focused window comes in, without toggling the focused application,
9287 * then no ANR should occur.
9288 *
9289 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
9290 * but in some cases the policy may not update the focused application.
9291 */
9292TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
9293 std::shared_ptr<FakeApplicationHandle> focusedApplication =
9294 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07009295 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009296 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
9297 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
9298 mFocusedWindow->setFocusable(false);
9299
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009300 mDispatcher->onWindowInfosChanged(
9301 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009302 mFocusedWindow->consumeFocusEvent(false);
9303
9304 // Send a key. The ANR timer should start because there is no focused window.
9305 // 'focusedApplication' will get blamed if this timer completes.
9306 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009307 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009308 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9309 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00009310 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009311 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009312
9313 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
9314 // then the injected touches won't cause the focused event to get dropped.
9315 // The dispatcher only checks for whether the queue should be pruned upon queueing.
9316 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
9317 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
9318 // For this test, it means that the key would get delivered to the window once it becomes
9319 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009320 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009321
9322 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00009323 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9324 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9325 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009326
9327 // We do not consume the motion right away, because that would require dispatcher to first
9328 // process (== drop) the key event, and by that time, ANR will be raised.
9329 // Set the focused window first.
9330 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009331 mDispatcher->onWindowInfosChanged(
9332 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009333 setFocusedWindow(mFocusedWindow);
9334 mFocusedWindow->consumeFocusEvent(true);
9335 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
9336 // to another application. This could be a bug / behaviour in the policy.
9337
9338 mUnfocusedWindow->consumeMotionDown();
9339
9340 ASSERT_TRUE(mDispatcher->waitForIdle());
9341 // Should not ANR because we actually have a focused window. It was just added too slowly.
9342 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
9343}
9344
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -08009345/**
9346 * If we are pruning input queue, we should never drop pointer events. Otherwise, we risk having
9347 * an inconsistent event stream inside the dispatcher. In this test, we make sure that the
9348 * dispatcher doesn't prune pointer events incorrectly.
9349 *
9350 * This test reproduces a crash in InputDispatcher.
9351 * To reproduce the crash, we need to simulate the conditions for "pruning input queue" to occur.
9352 *
9353 * Keep the currently focused application (mApplication), and have no focused window.
9354 * We set up two additional windows:
9355 * 1) The navigation bar window. This simulates the system "NavigationBar", which is used in the
9356 * 3-button navigation mode. This window injects a BACK button when it's touched. 2) The application
9357 * window. This window is not focusable, but is touchable.
9358 *
9359 * We first touch the navigation bar, which causes it to inject a key. Since there's no focused
9360 * window, the dispatcher doesn't process this key, and all other events inside dispatcher are now
9361 * blocked. The dispatcher is waiting for 'mApplication' to add a focused window.
9362 *
9363 * Now, we touch "Another window". This window is owned by a different application than
9364 * 'mApplication'. This causes the dispatcher to stop waiting for 'mApplication' to add a focused
9365 * window. Now, the "pruning input queue" behaviour should kick in, and the dispatcher should start
9366 * dropping the events from its queue. Ensure that no crash occurs.
9367 *
9368 * In this test, we are setting long timeouts to prevent ANRs and events dropped due to being stale.
9369 * This does not affect the test running time.
9370 */
9371TEST_F(InputDispatcherMultiWindowAnr, PruningInputQueueShouldNotDropPointerEvents) {
9372 std::shared_ptr<FakeApplicationHandle> systemUiApplication =
9373 std::make_shared<FakeApplicationHandle>();
9374 systemUiApplication->setDispatchingTimeout(3000ms);
9375 mFakePolicy->setStaleEventTimeout(3000ms);
9376 sp<FakeWindowHandle> navigationBar =
9377 sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
9378 ADISPLAY_ID_DEFAULT);
9379 navigationBar->setFocusable(false);
9380 navigationBar->setWatchOutsideTouch(true);
9381 navigationBar->setFrame(Rect(0, 0, 100, 100));
9382
9383 mApplication->setDispatchingTimeout(3000ms);
9384 // 'mApplication' is already focused, but we call it again here to make it explicit.
9385 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
9386
9387 std::shared_ptr<FakeApplicationHandle> anotherApplication =
9388 std::make_shared<FakeApplicationHandle>();
9389 sp<FakeWindowHandle> appWindow =
9390 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
9391 ADISPLAY_ID_DEFAULT);
9392 appWindow->setFocusable(false);
9393 appWindow->setFrame(Rect(100, 100, 200, 200));
9394
9395 mDispatcher->onWindowInfosChanged(
9396 {{*navigationBar->getInfo(), *appWindow->getInfo()}, {}, 0, 0});
9397 // 'mFocusedWindow' is no longer in the dispatcher window list, and therefore loses focus
9398 mFocusedWindow->consumeFocusEvent(false);
9399
9400 // Touch down the navigation bar. It consumes the touch and injects a key into the dispatcher
9401 // in response.
9402 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9403 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9404 .build());
9405 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9406
9407 // Key will not be sent anywhere because we have no focused window. It will remain pending.
9408 // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
9409 InputEventInjectionResult result =
9410 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9411 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
9412 /*allowKeyRepeat=*/false);
9413 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
9414
9415 // Finish the gesture - lift up finger and inject ACTION_UP key event
9416 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9417 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9418 .build());
9419 result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9420 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
9421 /*allowKeyRepeat=*/false);
9422 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
9423 // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
9424 // getting any events yet.
9425 navigationBar->assertNoEvents();
9426
9427 // Now touch "Another window". This touch is going to a different application than the one we
9428 // are waiting for (which is 'mApplication').
9429 // This should cause the dispatcher to drop the pending focus-dispatched events (like the key
9430 // trying to be injected) and to continue processing the rest of the events in the original
9431 // order.
9432 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9433 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
9434 .build());
9435 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_UP));
9436 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
9437 appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9438
9439 appWindow->assertNoEvents();
9440 navigationBar->assertNoEvents();
9441}
9442
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009443// These tests ensure we cannot send touch events to a window that's positioned behind a window
9444// that has feature NO_INPUT_CHANNEL.
9445// Layout:
9446// Top (closest to user)
9447// mNoInputWindow (above all windows)
9448// mBottomWindow
9449// Bottom (furthest from user)
9450class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
9451 virtual void SetUp() override {
9452 InputDispatcherTest::SetUp();
9453
9454 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009455 mNoInputWindow =
9456 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
9457 "Window without input channel", ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009458 /*createInputChannel=*/false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009459 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009460 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
9461 // It's perfectly valid for this window to not have an associated input channel
9462
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009463 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
9464 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009465 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
9466
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009467 mDispatcher->onWindowInfosChanged(
9468 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009469 }
9470
9471protected:
9472 std::shared_ptr<FakeApplicationHandle> mApplication;
9473 sp<FakeWindowHandle> mNoInputWindow;
9474 sp<FakeWindowHandle> mBottomWindow;
9475};
9476
9477TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
9478 PointF touchedPoint = {10, 10};
9479
Prabir Pradhan678438e2023-04-13 19:32:51 +00009480 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9481 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9482 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009483
9484 mNoInputWindow->assertNoEvents();
9485 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
9486 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
9487 // and therefore should prevent mBottomWindow from receiving touches
9488 mBottomWindow->assertNoEvents();
9489}
9490
9491/**
9492 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
9493 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
9494 */
9495TEST_F(InputDispatcherMultiWindowOcclusionTests,
9496 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009497 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
9498 "Window with input channel and NO_INPUT_CHANNEL",
9499 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009500
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009501 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009502 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009503 mDispatcher->onWindowInfosChanged(
9504 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009505
9506 PointF touchedPoint = {10, 10};
9507
Prabir Pradhan678438e2023-04-13 19:32:51 +00009508 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9509 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9510 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009511
9512 mNoInputWindow->assertNoEvents();
9513 mBottomWindow->assertNoEvents();
9514}
9515
Vishnu Nair958da932020-08-21 17:12:37 -07009516class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
9517protected:
9518 std::shared_ptr<FakeApplicationHandle> mApp;
9519 sp<FakeWindowHandle> mWindow;
9520 sp<FakeWindowHandle> mMirror;
9521
9522 virtual void SetUp() override {
9523 InputDispatcherTest::SetUp();
9524 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009525 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009526 mMirror = mWindow->clone(ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07009527 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
9528 mWindow->setFocusable(true);
9529 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009530 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009531 }
9532};
9533
9534TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
9535 // Request focus on a mirrored window
9536 setFocusedWindow(mMirror);
9537
9538 // window gets focused
9539 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009540 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009541 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009542 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
9543}
9544
9545// A focused & mirrored window remains focused only if the window and its mirror are both
9546// focusable.
9547TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
9548 setFocusedWindow(mMirror);
9549
9550 // window gets focused
9551 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009552 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009553 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009554 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009555 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009556 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009557 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9558
9559 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009560 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009561
9562 // window loses focus since one of the windows associated with the token in not focusable
9563 mWindow->consumeFocusEvent(false);
9564
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009565 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009566 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009567 mWindow->assertNoEvents();
9568}
9569
9570// A focused & mirrored window remains focused until the window and its mirror both become
9571// invisible.
9572TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
9573 setFocusedWindow(mMirror);
9574
9575 // window gets focused
9576 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009577 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009578 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009579 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009580 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009581 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009582 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9583
9584 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009585 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009586
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009587 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009588 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009589 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009590 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009591 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009592 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9593
9594 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009595 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009596
9597 // window loses focus only after all windows associated with the token become invisible.
9598 mWindow->consumeFocusEvent(false);
9599
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009600 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009601 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009602 mWindow->assertNoEvents();
9603}
9604
9605// A focused & mirrored window remains focused until both windows are removed.
9606TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
9607 setFocusedWindow(mMirror);
9608
9609 // window gets focused
9610 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009611 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009612 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009613 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009614 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009615 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009616 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9617
9618 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009619 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009620
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009621 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009622 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009623 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009624 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009625 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009626 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9627
9628 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009629 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009630 mWindow->consumeFocusEvent(false);
9631
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009632 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009633 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009634 mWindow->assertNoEvents();
9635}
9636
9637// Focus request can be pending until one window becomes visible.
9638TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
9639 // Request focus on an invisible mirror.
9640 mWindow->setVisible(false);
9641 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009642 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009643 setFocusedWindow(mMirror);
9644
9645 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009646 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009647 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9648 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07009649
9650 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009651 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009652
9653 // window gets focused
9654 mWindow->consumeFocusEvent(true);
9655 // window gets the pending key event
9656 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9657}
Prabir Pradhan99987712020-11-10 18:43:05 -08009658
9659class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
9660protected:
9661 std::shared_ptr<FakeApplicationHandle> mApp;
9662 sp<FakeWindowHandle> mWindow;
9663 sp<FakeWindowHandle> mSecondWindow;
9664
9665 void SetUp() override {
9666 InputDispatcherTest::SetUp();
9667 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009668 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009669 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009670 mSecondWindow =
9671 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009672 mSecondWindow->setFocusable(true);
9673
9674 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009675 mDispatcher->onWindowInfosChanged(
9676 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08009677
9678 setFocusedWindow(mWindow);
9679 mWindow->consumeFocusEvent(true);
9680 }
9681
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009682 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009683 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08009684 }
9685
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009686 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
9687 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08009688 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009689 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
9690 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009691 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009692 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08009693 }
9694};
9695
9696TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
9697 // Ensure that capture cannot be obtained for unfocused windows.
9698 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
9699 mFakePolicy->assertSetPointerCaptureNotCalled();
9700 mSecondWindow->assertNoEvents();
9701
9702 // Ensure that capture can be enabled from the focus window.
9703 requestAndVerifyPointerCapture(mWindow, true);
9704
9705 // Ensure that capture cannot be disabled from a window that does not have capture.
9706 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
9707 mFakePolicy->assertSetPointerCaptureNotCalled();
9708
9709 // Ensure that capture can be disabled from the window with capture.
9710 requestAndVerifyPointerCapture(mWindow, false);
9711}
9712
9713TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009714 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009715
9716 setFocusedWindow(mSecondWindow);
9717
9718 // Ensure that the capture disabled event was sent first.
9719 mWindow->consumeCaptureEvent(false);
9720 mWindow->consumeFocusEvent(false);
9721 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009722 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009723
9724 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009725 notifyPointerCaptureChanged({});
9726 notifyPointerCaptureChanged(request);
9727 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08009728 mWindow->assertNoEvents();
9729 mSecondWindow->assertNoEvents();
9730 mFakePolicy->assertSetPointerCaptureNotCalled();
9731}
9732
9733TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009734 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009735
9736 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009737 notifyPointerCaptureChanged({});
9738 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009739
9740 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009741 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009742 mWindow->consumeCaptureEvent(false);
9743 mWindow->assertNoEvents();
9744}
9745
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009746TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
9747 requestAndVerifyPointerCapture(mWindow, true);
9748
9749 // The first window loses focus.
9750 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009751 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009752 mWindow->consumeCaptureEvent(false);
9753
9754 // Request Pointer Capture from the second window before the notification from InputReader
9755 // arrives.
9756 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009757 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009758
9759 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009760 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009761
9762 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009763 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009764
9765 mSecondWindow->consumeFocusEvent(true);
9766 mSecondWindow->consumeCaptureEvent(true);
9767}
9768
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009769TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
9770 // App repeatedly enables and disables capture.
9771 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9772 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9773 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9774 mFakePolicy->assertSetPointerCaptureCalled(false);
9775 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9776 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9777
9778 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
9779 // first request is now stale, this should do nothing.
9780 notifyPointerCaptureChanged(firstRequest);
9781 mWindow->assertNoEvents();
9782
9783 // InputReader notifies that the second request was enabled.
9784 notifyPointerCaptureChanged(secondRequest);
9785 mWindow->consumeCaptureEvent(true);
9786}
9787
Prabir Pradhan7092e262022-05-03 16:51:09 +00009788TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
9789 requestAndVerifyPointerCapture(mWindow, true);
9790
9791 // App toggles pointer capture off and on.
9792 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9793 mFakePolicy->assertSetPointerCaptureCalled(false);
9794
9795 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9796 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9797
9798 // InputReader notifies that the latest "enable" request was processed, while skipping over the
9799 // preceding "disable" request.
9800 notifyPointerCaptureChanged(enableRequest);
9801
9802 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
9803 // any notifications.
9804 mWindow->assertNoEvents();
9805}
9806
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009807/**
9808 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
9809 * mouse movements don't affect the previous mouse hovering state.
9810 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
9811 * HOVER_MOVE events).
9812 */
9813TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
9814 // Mouse hover on the window
9815 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
9816 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9817 .build());
9818 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9819 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9820 .build());
9821
9822 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
9823 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
9824
9825 // Start pointer capture
9826 requestAndVerifyPointerCapture(mWindow, true);
9827
9828 // Send some relative mouse movements and receive them in the window.
9829 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
9830 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
9831 .build());
9832 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
9833 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
9834
9835 // Stop pointer capture
9836 requestAndVerifyPointerCapture(mWindow, false);
9837
9838 // Continue hovering on the window
9839 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9840 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
9841 .build());
9842 mWindow->consumeMotionEvent(
9843 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
9844
9845 mWindow->assertNoEvents();
9846}
9847
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009848class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
9849protected:
9850 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00009851
9852 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
9853 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
9854
9855 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
9856 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9857
9858 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
9859 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
9860 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9861 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
9862 MAXIMUM_OBSCURING_OPACITY);
9863
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009864 static constexpr gui::Uid TOUCHED_APP_UID{10001};
9865 static constexpr gui::Uid APP_B_UID{10002};
9866 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009867
9868 sp<FakeWindowHandle> mTouchWindow;
9869
9870 virtual void SetUp() override {
9871 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009872 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009873 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
9874 }
9875
9876 virtual void TearDown() override {
9877 InputDispatcherTest::TearDown();
9878 mTouchWindow.clear();
9879 }
9880
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009881 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05009882 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009883 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009884 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009885 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009886 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009887 return window;
9888 }
9889
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009890 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009891 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
9892 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009893 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009894 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009895 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009896 return window;
9897 }
9898
9899 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009900 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9901 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9902 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009903 }
9904};
9905
9906TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009907 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009908 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009909 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009910
9911 touch();
9912
9913 mTouchWindow->assertNoEvents();
9914}
9915
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009916TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00009917 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
9918 const sp<FakeWindowHandle>& w =
9919 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009920 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009921
9922 touch();
9923
9924 mTouchWindow->assertNoEvents();
9925}
9926
9927TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009928 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
9929 const sp<FakeWindowHandle>& w =
9930 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009931 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009932
9933 touch();
9934
9935 w->assertNoEvents();
9936}
9937
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009938TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009939 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009940 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009941
9942 touch();
9943
9944 mTouchWindow->consumeAnyMotionDown();
9945}
9946
9947TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009948 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009949 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009950 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009951 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009952
9953 touch({PointF{100, 100}});
9954
9955 mTouchWindow->consumeAnyMotionDown();
9956}
9957
9958TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009959 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009960 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009961 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009962
9963 touch();
9964
9965 mTouchWindow->consumeAnyMotionDown();
9966}
9967
9968TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
9969 const sp<FakeWindowHandle>& w =
9970 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009971 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009972
9973 touch();
9974
9975 mTouchWindow->consumeAnyMotionDown();
9976}
9977
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009978TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
9979 const sp<FakeWindowHandle>& w =
9980 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009981 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009982
9983 touch();
9984
9985 w->assertNoEvents();
9986}
9987
9988/**
9989 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
9990 * inside) while letting them pass-through. Note that even though touch passes through the occluding
9991 * window, the occluding window will still receive ACTION_OUTSIDE event.
9992 */
9993TEST_F(InputDispatcherUntrustedTouchesTest,
9994 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
9995 const sp<FakeWindowHandle>& w =
9996 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009997 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009998 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009999
10000 touch();
10001
10002 w->consumeMotionOutside();
10003}
10004
10005TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
10006 const sp<FakeWindowHandle>& w =
10007 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010008 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010009 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010010
10011 touch();
10012
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010013 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010014}
10015
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010016TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010017 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010018 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10019 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010020 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010021
10022 touch();
10023
10024 mTouchWindow->consumeAnyMotionDown();
10025}
10026
10027TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
10028 const sp<FakeWindowHandle>& w =
10029 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10030 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010031 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010032
10033 touch();
10034
10035 mTouchWindow->consumeAnyMotionDown();
10036}
10037
10038TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010039 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010040 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10041 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010042 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010043
10044 touch();
10045
10046 mTouchWindow->assertNoEvents();
10047}
10048
10049TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
10050 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
10051 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010052 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
10053 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010054 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010055 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
10056 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010057 mDispatcher->onWindowInfosChanged(
10058 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010059
10060 touch();
10061
10062 mTouchWindow->assertNoEvents();
10063}
10064
10065TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
10066 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
10067 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010068 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
10069 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010070 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010071 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
10072 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010073 mDispatcher->onWindowInfosChanged(
10074 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010075
10076 touch();
10077
10078 mTouchWindow->consumeAnyMotionDown();
10079}
10080
10081TEST_F(InputDispatcherUntrustedTouchesTest,
10082 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
10083 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010084 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10085 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010086 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010087 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10088 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010089 mDispatcher->onWindowInfosChanged(
10090 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010091
10092 touch();
10093
10094 mTouchWindow->consumeAnyMotionDown();
10095}
10096
10097TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
10098 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010099 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10100 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010101 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010102 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10103 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010104 mDispatcher->onWindowInfosChanged(
10105 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010106
10107 touch();
10108
10109 mTouchWindow->assertNoEvents();
10110}
10111
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010112TEST_F(InputDispatcherUntrustedTouchesTest,
10113 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
10114 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010115 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10116 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010117 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010118 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10119 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010120 mDispatcher->onWindowInfosChanged(
10121 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010122
10123 touch();
10124
10125 mTouchWindow->assertNoEvents();
10126}
10127
10128TEST_F(InputDispatcherUntrustedTouchesTest,
10129 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
10130 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010131 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10132 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010133 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010134 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10135 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010136 mDispatcher->onWindowInfosChanged(
10137 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010138
10139 touch();
10140
10141 mTouchWindow->consumeAnyMotionDown();
10142}
10143
10144TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
10145 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010146 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10147 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010148 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010149
10150 touch();
10151
10152 mTouchWindow->consumeAnyMotionDown();
10153}
10154
10155TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
10156 const sp<FakeWindowHandle>& w =
10157 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010158 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010159
10160 touch();
10161
10162 mTouchWindow->consumeAnyMotionDown();
10163}
10164
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010165TEST_F(InputDispatcherUntrustedTouchesTest,
10166 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
10167 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
10168 const sp<FakeWindowHandle>& w =
10169 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010170 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010171
10172 touch();
10173
10174 mTouchWindow->assertNoEvents();
10175}
10176
10177TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
10178 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
10179 const sp<FakeWindowHandle>& w =
10180 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010181 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010182
10183 touch();
10184
10185 mTouchWindow->consumeAnyMotionDown();
10186}
10187
10188TEST_F(InputDispatcherUntrustedTouchesTest,
10189 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
10190 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
10191 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010192 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10193 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010194 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010195
10196 touch();
10197
10198 mTouchWindow->consumeAnyMotionDown();
10199}
10200
10201TEST_F(InputDispatcherUntrustedTouchesTest,
10202 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
10203 const sp<FakeWindowHandle>& w1 =
10204 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
10205 OPACITY_BELOW_THRESHOLD);
10206 const sp<FakeWindowHandle>& w2 =
10207 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10208 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010209 mDispatcher->onWindowInfosChanged(
10210 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010211
10212 touch();
10213
10214 mTouchWindow->assertNoEvents();
10215}
10216
10217/**
10218 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
10219 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
10220 * (which alone would result in allowing touches) does not affect the blocking behavior.
10221 */
10222TEST_F(InputDispatcherUntrustedTouchesTest,
10223 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
10224 const sp<FakeWindowHandle>& wB =
10225 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
10226 OPACITY_BELOW_THRESHOLD);
10227 const sp<FakeWindowHandle>& wC =
10228 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10229 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010230 mDispatcher->onWindowInfosChanged(
10231 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010232
10233 touch();
10234
10235 mTouchWindow->assertNoEvents();
10236}
10237
10238/**
10239 * This test is testing that a window from a different UID but with same application token doesn't
10240 * block the touch. Apps can share the application token for close UI collaboration for example.
10241 */
10242TEST_F(InputDispatcherUntrustedTouchesTest,
10243 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
10244 const sp<FakeWindowHandle>& w =
10245 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
10246 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010247 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010248
10249 touch();
10250
10251 mTouchWindow->consumeAnyMotionDown();
10252}
10253
arthurhungb89ccb02020-12-30 16:19:01 +080010254class InputDispatcherDragTests : public InputDispatcherTest {
10255protected:
10256 std::shared_ptr<FakeApplicationHandle> mApp;
10257 sp<FakeWindowHandle> mWindow;
10258 sp<FakeWindowHandle> mSecondWindow;
10259 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010260 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010261 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
10262 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +080010263
10264 void SetUp() override {
10265 InputDispatcherTest::SetUp();
10266 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010267 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080010268 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080010269
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010270 mSecondWindow =
10271 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080010272 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080010273
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010274 mSpyWindow =
10275 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010276 mSpyWindow->setSpy(true);
10277 mSpyWindow->setTrustedOverlay(true);
10278 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
10279
arthurhungb89ccb02020-12-30 16:19:01 +080010280 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010281 mDispatcher->onWindowInfosChanged(
10282 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
10283 {},
10284 0,
10285 0});
arthurhungb89ccb02020-12-30 16:19:01 +080010286 }
10287
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010288 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
10289 switch (fromSource) {
10290 case AINPUT_SOURCE_TOUCHSCREEN:
10291 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010292 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010293 ADISPLAY_ID_DEFAULT, {50, 50}))
10294 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10295 break;
10296 case AINPUT_SOURCE_STYLUS:
10297 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010298 injectMotionEvent(*mDispatcher,
10299 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10300 AINPUT_SOURCE_STYLUS)
10301 .buttonState(
10302 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
10303 .pointer(PointerBuilder(0, ToolType::STYLUS)
10304 .x(50)
10305 .y(50))
10306 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010307 break;
10308 case AINPUT_SOURCE_MOUSE:
10309 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010310 injectMotionEvent(*mDispatcher,
10311 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10312 AINPUT_SOURCE_MOUSE)
10313 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
10314 .pointer(PointerBuilder(MOUSE_POINTER_ID,
10315 ToolType::MOUSE)
10316 .x(50)
10317 .y(50))
10318 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010319 break;
10320 default:
10321 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
10322 }
arthurhungb89ccb02020-12-30 16:19:01 +080010323
10324 // Window should receive motion event.
10325 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010326 // Spy window should also receive motion event
10327 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000010328 }
10329
10330 // Start performing drag, we will create a drag window and transfer touch to it.
10331 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
10332 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010333 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +000010334 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010335 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +000010336 }
arthurhungb89ccb02020-12-30 16:19:01 +080010337
10338 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010339 mDragWindow =
10340 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010341 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010342 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
10343 *mWindow->getInfo(), *mSecondWindow->getInfo()},
10344 {},
10345 0,
10346 0});
arthurhungb89ccb02020-12-30 16:19:01 +080010347
10348 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +000010349 bool transferred =
10350 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +000010351 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +000010352 if (transferred) {
10353 mWindow->consumeMotionCancel();
10354 mDragWindow->consumeMotionDown();
10355 }
10356 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +080010357 }
10358};
10359
10360TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010361 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +080010362
10363 // Move on window.
10364 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010365 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010366 ADISPLAY_ID_DEFAULT, {50, 50}))
10367 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10368 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10369 mWindow->consumeDragEvent(false, 50, 50);
10370 mSecondWindow->assertNoEvents();
10371
10372 // Move to another window.
10373 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010374 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010375 ADISPLAY_ID_DEFAULT, {150, 50}))
10376 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10377 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10378 mWindow->consumeDragEvent(true, 150, 50);
10379 mSecondWindow->consumeDragEvent(false, 50, 50);
10380
10381 // Move back to original window.
10382 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010383 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010384 ADISPLAY_ID_DEFAULT, {50, 50}))
10385 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10386 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10387 mWindow->consumeDragEvent(false, 50, 50);
10388 mSecondWindow->consumeDragEvent(true, -50, 50);
10389
10390 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010391 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10392 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080010393 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10394 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10395 mWindow->assertNoEvents();
10396 mSecondWindow->assertNoEvents();
10397}
10398
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010399TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010400 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010401
10402 // No cancel event after drag start
10403 mSpyWindow->assertNoEvents();
10404
10405 const MotionEvent secondFingerDownEvent =
10406 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10407 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010408 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10409 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010410 .build();
10411 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010412 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010413 InputEventInjectionSync::WAIT_FOR_RESULT))
10414 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10415
10416 // Receives cancel for first pointer after next pointer down
10417 mSpyWindow->consumeMotionCancel();
10418 mSpyWindow->consumeMotionDown();
10419
10420 mSpyWindow->assertNoEvents();
10421}
10422
arthurhungf452d0b2021-01-06 00:19:52 +080010423TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010424 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +080010425
10426 // Move on window.
10427 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010428 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +080010429 ADISPLAY_ID_DEFAULT, {50, 50}))
10430 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10431 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10432 mWindow->consumeDragEvent(false, 50, 50);
10433 mSecondWindow->assertNoEvents();
10434
10435 // Move to another window.
10436 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010437 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +080010438 ADISPLAY_ID_DEFAULT, {150, 50}))
10439 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10440 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10441 mWindow->consumeDragEvent(true, 150, 50);
10442 mSecondWindow->consumeDragEvent(false, 50, 50);
10443
10444 // drop to another window.
10445 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010446 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +080010447 {150, 50}))
10448 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10449 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010450 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +080010451 mWindow->assertNoEvents();
10452 mSecondWindow->assertNoEvents();
10453}
10454
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010455TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
10456 startDrag();
10457
10458 // No cancel event after drag start
10459 mSpyWindow->assertNoEvents();
10460
10461 const MotionEvent secondFingerDownEvent =
10462 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10463 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10464 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10465 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10466 .build();
10467 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10468 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10469 InputEventInjectionSync::WAIT_FOR_RESULT))
10470 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10471
10472 // Receives cancel for first pointer after next pointer down
10473 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080010474 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010475 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
10476
10477 mSpyWindow->assertNoEvents();
10478
10479 // Spy window calls pilfer pointers
10480 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
10481 mDragWindow->assertNoEvents();
10482
10483 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010484 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010485 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10486 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
10487 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10488 .build();
10489 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010490 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010491 InputEventInjectionSync::WAIT_FOR_RESULT))
10492 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10493
10494 // Drag window should still receive the new event
10495 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
10496 mDragWindow->assertNoEvents();
10497}
10498
arthurhung6d4bed92021-03-17 11:59:33 +080010499TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010500 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +080010501
10502 // Move on window and keep button pressed.
10503 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010504 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010505 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10506 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010507 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010508 .build()))
10509 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10510 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10511 mWindow->consumeDragEvent(false, 50, 50);
10512 mSecondWindow->assertNoEvents();
10513
10514 // Move to another window and release button, expect to drop item.
10515 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010516 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010517 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10518 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010519 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010520 .build()))
10521 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10522 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10523 mWindow->assertNoEvents();
10524 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010525 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +080010526
10527 // nothing to the window.
10528 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010529 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010530 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
10531 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010532 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010533 .build()))
10534 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10535 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10536 mWindow->assertNoEvents();
10537 mSecondWindow->assertNoEvents();
10538}
10539
Arthur Hung54745652022-04-20 07:17:41 +000010540TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010541 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +080010542
10543 // Set second window invisible.
10544 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010545 mDispatcher->onWindowInfosChanged(
10546 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +080010547
10548 // Move on window.
10549 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010550 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010551 ADISPLAY_ID_DEFAULT, {50, 50}))
10552 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10553 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10554 mWindow->consumeDragEvent(false, 50, 50);
10555 mSecondWindow->assertNoEvents();
10556
10557 // Move to another window.
10558 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010559 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010560 ADISPLAY_ID_DEFAULT, {150, 50}))
10561 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10562 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10563 mWindow->consumeDragEvent(true, 150, 50);
10564 mSecondWindow->assertNoEvents();
10565
10566 // drop to another window.
10567 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010568 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010569 {150, 50}))
10570 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10571 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010572 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010573 mWindow->assertNoEvents();
10574 mSecondWindow->assertNoEvents();
10575}
10576
Arthur Hung54745652022-04-20 07:17:41 +000010577TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010578 // Ensure window could track pointerIds if it didn't support split touch.
10579 mWindow->setPreventSplitting(true);
10580
Arthur Hung54745652022-04-20 07:17:41 +000010581 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010582 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010583 {50, 50}))
10584 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10585 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10586
10587 const MotionEvent secondFingerDownEvent =
10588 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10589 .displayId(ADISPLAY_ID_DEFAULT)
10590 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010591 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10592 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010593 .build();
10594 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010595 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010596 InputEventInjectionSync::WAIT_FOR_RESULT))
10597 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010598 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +000010599
10600 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010601 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010602}
10603
10604TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
10605 // First down on second window.
10606 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010607 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010608 {150, 50}))
10609 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10610
10611 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10612
10613 // Second down on first window.
10614 const MotionEvent secondFingerDownEvent =
10615 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10616 .displayId(ADISPLAY_ID_DEFAULT)
10617 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010618 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10619 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010620 .build();
10621 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010622 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010623 InputEventInjectionSync::WAIT_FOR_RESULT))
10624 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10625 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10626
10627 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010628 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010629
10630 // Move on window.
10631 const MotionEvent secondFingerMoveEvent =
10632 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10633 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010634 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10635 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010636 .build();
10637 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010638 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010639 InputEventInjectionSync::WAIT_FOR_RESULT));
10640 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10641 mWindow->consumeDragEvent(false, 50, 50);
10642 mSecondWindow->consumeMotionMove();
10643
10644 // Release the drag pointer should perform drop.
10645 const MotionEvent secondFingerUpEvent =
10646 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10647 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010648 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10649 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010650 .build();
10651 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010652 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010653 InputEventInjectionSync::WAIT_FOR_RESULT));
10654 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010655 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000010656 mWindow->assertNoEvents();
10657 mSecondWindow->consumeMotionMove();
10658}
10659
Arthur Hung3915c1f2022-05-31 07:17:17 +000010660TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010661 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000010662
10663 // Update window of second display.
10664 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010665 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010666 mDispatcher->onWindowInfosChanged(
10667 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10668 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10669 {},
10670 0,
10671 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010672
10673 // Let second display has a touch state.
10674 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010675 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010676 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10677 AINPUT_SOURCE_TOUCHSCREEN)
10678 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010679 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000010680 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000010681 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010682 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010683 mDispatcher->onWindowInfosChanged(
10684 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10685 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10686 {},
10687 0,
10688 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010689
10690 // Move on window.
10691 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010692 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010693 ADISPLAY_ID_DEFAULT, {50, 50}))
10694 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10695 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10696 mWindow->consumeDragEvent(false, 50, 50);
10697 mSecondWindow->assertNoEvents();
10698
10699 // Move to another window.
10700 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010701 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010702 ADISPLAY_ID_DEFAULT, {150, 50}))
10703 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10704 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10705 mWindow->consumeDragEvent(true, 150, 50);
10706 mSecondWindow->consumeDragEvent(false, 50, 50);
10707
10708 // drop to another window.
10709 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010710 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010711 {150, 50}))
10712 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10713 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010714 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000010715 mWindow->assertNoEvents();
10716 mSecondWindow->assertNoEvents();
10717}
10718
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010719TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
10720 startDrag(true, AINPUT_SOURCE_MOUSE);
10721 // Move on window.
10722 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010723 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010724 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10725 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010726 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010727 .x(50)
10728 .y(50))
10729 .build()))
10730 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10731 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10732 mWindow->consumeDragEvent(false, 50, 50);
10733 mSecondWindow->assertNoEvents();
10734
10735 // Move to another window.
10736 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010737 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010738 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10739 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010740 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010741 .x(150)
10742 .y(50))
10743 .build()))
10744 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10745 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10746 mWindow->consumeDragEvent(true, 150, 50);
10747 mSecondWindow->consumeDragEvent(false, 50, 50);
10748
10749 // drop to another window.
10750 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010751 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010752 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
10753 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010754 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010755 .x(150)
10756 .y(50))
10757 .build()))
10758 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10759 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010760 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010761 mWindow->assertNoEvents();
10762 mSecondWindow->assertNoEvents();
10763}
10764
Linnan Li5af92f92023-07-14 14:36:22 +080010765/**
10766 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
10767 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
10768 */
10769TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
10770 // Down on second window
10771 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10772 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10773 {150, 50}))
10774 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10775
10776 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
10777 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
10778
10779 // Down on first window
10780 const MotionEvent secondFingerDownEvent =
10781 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10782 .displayId(ADISPLAY_ID_DEFAULT)
10783 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10784 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10785 .build();
10786 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10787 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10788 InputEventInjectionSync::WAIT_FOR_RESULT))
10789 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10790 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10791 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
10792 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
10793
10794 // Start drag on first window
10795 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
10796
10797 // Trigger cancel
10798 mDispatcher->cancelCurrentTouch();
10799 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
10800 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
10801 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
10802
10803 ASSERT_TRUE(mDispatcher->waitForIdle());
10804 // The D&D finished with nullptr
10805 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
10806
10807 // Remove drag window
10808 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
10809
10810 // Inject a simple gesture, ensure dispatcher not crashed
10811 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10812 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10813 PointF{50, 50}))
10814 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10815 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10816
10817 const MotionEvent moveEvent =
10818 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10819 .displayId(ADISPLAY_ID_DEFAULT)
10820 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10821 .build();
10822 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10823 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
10824 InputEventInjectionSync::WAIT_FOR_RESULT))
10825 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10826 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
10827
10828 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10829 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10830 {50, 50}))
10831 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10832 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
10833}
10834
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000010835TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
10836 // Start hovering over the window.
10837 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10838 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
10839 ADISPLAY_ID_DEFAULT, {50, 50}));
10840
10841 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10842 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10843
10844 ASSERT_FALSE(startDrag(/*sendDown=*/false))
10845 << "Drag and drop should not work with a hovering pointer";
10846}
10847
Vishnu Nair062a8672021-09-03 16:07:44 -070010848class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
10849
10850TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
10851 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010852 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10853 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010854 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010855 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10856 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010857 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010858 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010859 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010860
10861 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010862 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010863 window->assertNoEvents();
10864
Prabir Pradhan678438e2023-04-13 19:32:51 +000010865 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10866 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010867 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10868 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080010869 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070010870 window->assertNoEvents();
10871
10872 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010873 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010874 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010875
Prabir Pradhan678438e2023-04-13 19:32:51 +000010876 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010877 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10878
Prabir Pradhan678438e2023-04-13 19:32:51 +000010879 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10880 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010881 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10882 window->assertNoEvents();
10883}
10884
10885TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
10886 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10887 std::make_shared<FakeApplicationHandle>();
10888 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010889 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10890 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010891 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010892 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010893 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010894 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010895 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10896 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010897 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010898 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010899 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10900 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010901 mDispatcher->onWindowInfosChanged(
10902 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010903 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010904 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010905
10906 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010907 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010908 window->assertNoEvents();
10909
Prabir Pradhan678438e2023-04-13 19:32:51 +000010910 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10911 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010912 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10913 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010914 window->assertNoEvents();
10915
10916 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010917 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010918 mDispatcher->onWindowInfosChanged(
10919 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010920
Prabir Pradhan678438e2023-04-13 19:32:51 +000010921 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010922 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10923
Prabir Pradhan678438e2023-04-13 19:32:51 +000010924 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10925 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010926 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
10927 window->assertNoEvents();
10928}
10929
10930TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
10931 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10932 std::make_shared<FakeApplicationHandle>();
10933 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010934 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10935 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010936 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010937 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010938 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010939 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010940 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10941 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010942 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010943 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010944 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10945 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010946 mDispatcher->onWindowInfosChanged(
10947 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010948 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010949 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010950
10951 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010952 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010953 window->assertNoEvents();
10954
Prabir Pradhan678438e2023-04-13 19:32:51 +000010955 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10956 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010957 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10958 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010959 window->assertNoEvents();
10960
10961 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010962 mDispatcher->onWindowInfosChanged(
10963 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010964
Prabir Pradhan678438e2023-04-13 19:32:51 +000010965 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010966 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10967
Prabir Pradhan678438e2023-04-13 19:32:51 +000010968 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10969 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010970 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10971 window->assertNoEvents();
10972}
10973
Antonio Kantekf16f2832021-09-28 04:39:20 +000010974class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
10975protected:
10976 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000010977 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010978 sp<FakeWindowHandle> mWindow;
10979 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000010980 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010981
10982 void SetUp() override {
10983 InputDispatcherTest::SetUp();
10984
10985 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000010986 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010987 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010988 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010989 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010990 mSecondWindow =
10991 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010992 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000010993 mThirdWindow =
10994 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
10995 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
10996 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010997
10998 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010999 mDispatcher->onWindowInfosChanged(
11000 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
11001 {},
11002 0,
11003 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000011004 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011005 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011006
Antonio Kantek15beb512022-06-13 22:35:41 +000011007 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000011008 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000011009 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070011010 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
11011 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000011012 mThirdWindow->assertNoEvents();
11013 }
11014
11015 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
11016 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000011017 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000011018 SECOND_DISPLAY_ID)) {
11019 mWindow->assertNoEvents();
11020 mSecondWindow->assertNoEvents();
11021 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070011022 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000011023 }
11024
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011025 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000011026 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070011027 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
11028 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000011029 mWindow->consumeTouchModeEvent(inTouchMode);
11030 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000011031 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000011032 }
11033};
11034
Antonio Kantek26defcf2022-02-08 01:12:27 +000011035TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080011036 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000011037 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
11038 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011039 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011040}
11041
Antonio Kantek26defcf2022-02-08 01:12:27 +000011042TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
11043 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011044 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011045 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011046 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011047 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000011048 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -070011049 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000011050 mWindow->assertNoEvents();
11051 mSecondWindow->assertNoEvents();
11052}
11053
11054TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
11055 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011056 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011057 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011058 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000011059 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000011060 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011061}
11062
Antonio Kantekf16f2832021-09-28 04:39:20 +000011063TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080011064 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000011065 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
11066 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011067 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000011068 mWindow->assertNoEvents();
11069 mSecondWindow->assertNoEvents();
11070}
11071
Antonio Kantek15beb512022-06-13 22:35:41 +000011072TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
11073 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
11074 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
11075 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011076 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000011077 mWindow->assertNoEvents();
11078 mSecondWindow->assertNoEvents();
11079 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
11080}
11081
Antonio Kantek48710e42022-03-24 14:19:30 -070011082TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
11083 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011084 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11085 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070011086 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11087 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
11088
11089 // Then remove focus.
11090 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011091 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070011092
11093 // Assert that caller can switch touch mode by owning one of the last interacted window.
11094 const WindowInfo& windowInfo = *mWindow->getInfo();
11095 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
11096 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011097 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070011098}
11099
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011100class InputDispatcherSpyWindowTest : public InputDispatcherTest {
11101public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011102 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011103 std::shared_ptr<FakeApplicationHandle> application =
11104 std::make_shared<FakeApplicationHandle>();
11105 std::string name = "Fake Spy ";
11106 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011107 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
11108 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011109 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011110 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011111 return spy;
11112 }
11113
11114 sp<FakeWindowHandle> createForeground() {
11115 std::shared_ptr<FakeApplicationHandle> application =
11116 std::make_shared<FakeApplicationHandle>();
11117 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011118 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
11119 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011120 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011121 return window;
11122 }
11123
11124private:
11125 int mSpyCount{0};
11126};
11127
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011128using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011129/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011130 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
11131 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011132TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070011133 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011134 ScopedSilentDeath _silentDeath;
11135
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011136 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011137 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011138 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011139 ".* not a trusted overlay");
11140}
11141
11142/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011143 * Input injection into a display with a spy window but no foreground windows should succeed.
11144 */
11145TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011146 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011147 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011148
11149 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011150 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011151 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11152 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11153}
11154
11155/**
11156 * Verify the order in which different input windows receive events. The touched foreground window
11157 * (if there is one) should always receive the event first. When there are multiple spy windows, the
11158 * spy windows will receive the event according to their Z-order, where the top-most spy window will
11159 * receive events before ones belows it.
11160 *
11161 * Here, we set up a scenario with four windows in the following Z order from the top:
11162 * spy1, spy2, window, spy3.
11163 * We then inject an event and verify that the foreground "window" receives it first, followed by
11164 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
11165 * window.
11166 */
11167TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
11168 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011169 auto spy1 = createSpy();
11170 auto spy2 = createSpy();
11171 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011172 mDispatcher->onWindowInfosChanged(
11173 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011174 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
11175 const size_t numChannels = channels.size();
11176
Michael Wright8e9a8562022-02-09 13:44:29 +000011177 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011178 if (!epollFd.ok()) {
11179 FAIL() << "Failed to create epoll fd";
11180 }
11181
11182 for (size_t i = 0; i < numChannels; i++) {
11183 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
11184 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
11185 FAIL() << "Failed to add fd to epoll";
11186 }
11187 }
11188
11189 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011190 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011191 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11192
11193 std::vector<size_t> eventOrder;
11194 std::vector<struct epoll_event> events(numChannels);
11195 for (;;) {
11196 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
11197 (100ms).count());
11198 if (nFds < 0) {
11199 FAIL() << "Failed to call epoll_wait";
11200 }
11201 if (nFds == 0) {
11202 break; // epoll_wait timed out
11203 }
11204 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070011205 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070011206 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011207 channels[i]->consumeMotionDown();
11208 }
11209 }
11210
11211 // Verify the order in which the events were received.
11212 EXPECT_EQ(3u, eventOrder.size());
11213 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
11214 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
11215 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
11216}
11217
11218/**
11219 * A spy window using the NOT_TOUCHABLE flag does not receive events.
11220 */
11221TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
11222 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011223 auto spy = createSpy();
11224 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011225 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011226
11227 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011228 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011229 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11230 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11231 spy->assertNoEvents();
11232}
11233
11234/**
11235 * A spy window will only receive gestures that originate within its touchable region. Gestures that
11236 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
11237 * to the window.
11238 */
11239TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
11240 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011241 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011242 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011243 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011244
11245 // Inject an event outside the spy window's touchable region.
11246 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011247 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011248 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11249 window->consumeMotionDown();
11250 spy->assertNoEvents();
11251 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011252 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011253 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11254 window->consumeMotionUp();
11255 spy->assertNoEvents();
11256
11257 // Inject an event inside the spy window's touchable region.
11258 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011259 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011260 {5, 10}))
11261 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11262 window->consumeMotionDown();
11263 spy->consumeMotionDown();
11264}
11265
11266/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011267 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011268 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011269 */
11270TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
11271 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011272 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011273 auto spy = createSpy();
11274 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011275 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011276 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011277 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011278
11279 // Inject an event outside the spy window's frame and touchable region.
11280 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011281 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011282 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011283 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11284 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011285 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011286}
11287
11288/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011289 * Even when a spy window spans over multiple foreground windows, the spy should receive all
11290 * pointers that are down within its bounds.
11291 */
11292TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
11293 auto windowLeft = createForeground();
11294 windowLeft->setFrame({0, 0, 100, 200});
11295 auto windowRight = createForeground();
11296 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011297 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011298 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011299 mDispatcher->onWindowInfosChanged(
11300 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011301
11302 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011303 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011304 {50, 50}))
11305 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11306 windowLeft->consumeMotionDown();
11307 spy->consumeMotionDown();
11308
11309 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011310 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011311 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011312 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11313 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011314 .build();
11315 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011316 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011317 InputEventInjectionSync::WAIT_FOR_RESULT))
11318 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11319 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000011320 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011321}
11322
11323/**
11324 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
11325 * the spy should receive the second pointer with ACTION_DOWN.
11326 */
11327TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
11328 auto window = createForeground();
11329 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011330 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011331 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011332 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011333
11334 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011335 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011336 {50, 50}))
11337 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11338 window->consumeMotionDown();
11339 spyRight->assertNoEvents();
11340
11341 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011342 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011343 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011344 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11345 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011346 .build();
11347 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011348 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011349 InputEventInjectionSync::WAIT_FOR_RESULT))
11350 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000011351 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011352 spyRight->consumeMotionDown();
11353}
11354
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011355/**
11356 * The spy window should not be able to affect whether or not touches are split. Only the foreground
11357 * windows should be allowed to control split touch.
11358 */
11359TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080011360 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011361 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011362 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080011363 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011364
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011365 auto window = createForeground();
11366 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011367
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011368 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011369
11370 // First finger down, no window touched.
11371 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011372 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011373 {100, 200}))
11374 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11375 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11376 window->assertNoEvents();
11377
11378 // Second finger down on window, the window should receive touch down.
11379 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011380 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011381 .displayId(ADISPLAY_ID_DEFAULT)
11382 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011383 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11384 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011385 .build();
11386 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011387 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011388 InputEventInjectionSync::WAIT_FOR_RESULT))
11389 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11390
11391 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000011392 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011393}
11394
11395/**
11396 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
11397 * do not receive key events.
11398 */
11399TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011400 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011401 spy->setFocusable(false);
11402
11403 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011404 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011405 setFocusedWindow(window);
11406 window->consumeFocusEvent(true);
11407
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011408 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011409 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11410 window->consumeKeyDown(ADISPLAY_ID_NONE);
11411
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011412 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011413 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11414 window->consumeKeyUp(ADISPLAY_ID_NONE);
11415
11416 spy->assertNoEvents();
11417}
11418
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011419using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
11420
11421/**
11422 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
11423 * are currently sent to any other windows - including other spy windows - will also be cancelled.
11424 */
11425TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
11426 auto window = createForeground();
11427 auto spy1 = createSpy();
11428 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011429 mDispatcher->onWindowInfosChanged(
11430 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011431
11432 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011433 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011434 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11435 window->consumeMotionDown();
11436 spy1->consumeMotionDown();
11437 spy2->consumeMotionDown();
11438
11439 // Pilfer pointers from the second spy window.
11440 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
11441 spy2->assertNoEvents();
11442 spy1->consumeMotionCancel();
11443 window->consumeMotionCancel();
11444
11445 // The rest of the gesture should only be sent to the second spy window.
11446 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011447 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011448 ADISPLAY_ID_DEFAULT))
11449 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11450 spy2->consumeMotionMove();
11451 spy1->assertNoEvents();
11452 window->assertNoEvents();
11453}
11454
11455/**
11456 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
11457 * in the middle of the gesture.
11458 */
11459TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
11460 auto window = createForeground();
11461 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011462 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011463
11464 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011465 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011466 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11467 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11468 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11469
11470 window->releaseChannel();
11471
11472 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11473
11474 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011475 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011476 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11477 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
11478}
11479
11480/**
11481 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
11482 * the spy, but not to any other windows.
11483 */
11484TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
11485 auto spy = createSpy();
11486 auto window = createForeground();
11487
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011488 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011489
11490 // First finger down on the window and the spy.
11491 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011492 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011493 {100, 200}))
11494 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11495 spy->consumeMotionDown();
11496 window->consumeMotionDown();
11497
11498 // Spy window pilfers the pointers.
11499 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11500 window->consumeMotionCancel();
11501
11502 // Second finger down on the window and spy, but the window should not receive the pointer down.
11503 const MotionEvent secondFingerDownEvent =
11504 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11505 .displayId(ADISPLAY_ID_DEFAULT)
11506 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011507 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11508 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011509 .build();
11510 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011511 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011512 InputEventInjectionSync::WAIT_FOR_RESULT))
11513 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11514
Harry Cutts33476232023-01-30 19:57:29 +000011515 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011516
11517 // Third finger goes down outside all windows, so injection should fail.
11518 const MotionEvent thirdFingerDownEvent =
11519 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11520 .displayId(ADISPLAY_ID_DEFAULT)
11521 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011522 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11523 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
11524 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011525 .build();
11526 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011527 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011528 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080011529 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011530
11531 spy->assertNoEvents();
11532 window->assertNoEvents();
11533}
11534
11535/**
11536 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
11537 */
11538TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
11539 auto spy = createSpy();
11540 spy->setFrame(Rect(0, 0, 100, 100));
11541 auto window = createForeground();
11542 window->setFrame(Rect(0, 0, 200, 200));
11543
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011544 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011545
11546 // First finger down on the window only
11547 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011548 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011549 {150, 150}))
11550 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11551 window->consumeMotionDown();
11552
11553 // Second finger down on the spy and window
11554 const MotionEvent secondFingerDownEvent =
11555 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11556 .displayId(ADISPLAY_ID_DEFAULT)
11557 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011558 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11559 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011560 .build();
11561 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011562 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011563 InputEventInjectionSync::WAIT_FOR_RESULT))
11564 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11565 spy->consumeMotionDown();
11566 window->consumeMotionPointerDown(1);
11567
11568 // Third finger down on the spy and window
11569 const MotionEvent thirdFingerDownEvent =
11570 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11571 .displayId(ADISPLAY_ID_DEFAULT)
11572 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011573 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11574 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
11575 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011576 .build();
11577 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011578 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011579 InputEventInjectionSync::WAIT_FOR_RESULT))
11580 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11581 spy->consumeMotionPointerDown(1);
11582 window->consumeMotionPointerDown(2);
11583
11584 // Spy window pilfers the pointers.
11585 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000011586 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
11587 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011588
11589 spy->assertNoEvents();
11590 window->assertNoEvents();
11591}
11592
11593/**
11594 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
11595 * other windows should be canceled. If this results in the cancellation of all pointers for some
11596 * window, then that window should receive ACTION_CANCEL.
11597 */
11598TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
11599 auto spy = createSpy();
11600 spy->setFrame(Rect(0, 0, 100, 100));
11601 auto window = createForeground();
11602 window->setFrame(Rect(0, 0, 200, 200));
11603
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011604 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011605
11606 // First finger down on both spy and window
11607 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011608 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011609 {10, 10}))
11610 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11611 window->consumeMotionDown();
11612 spy->consumeMotionDown();
11613
11614 // Second finger down on the spy and window
11615 const MotionEvent secondFingerDownEvent =
11616 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11617 .displayId(ADISPLAY_ID_DEFAULT)
11618 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011619 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11620 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011621 .build();
11622 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011623 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011624 InputEventInjectionSync::WAIT_FOR_RESULT))
11625 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11626 spy->consumeMotionPointerDown(1);
11627 window->consumeMotionPointerDown(1);
11628
11629 // Spy window pilfers the pointers.
11630 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11631 window->consumeMotionCancel();
11632
11633 spy->assertNoEvents();
11634 window->assertNoEvents();
11635}
11636
11637/**
11638 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
11639 * be sent to other windows
11640 */
11641TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
11642 auto spy = createSpy();
11643 spy->setFrame(Rect(0, 0, 100, 100));
11644 auto window = createForeground();
11645 window->setFrame(Rect(0, 0, 200, 200));
11646
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011647 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011648
11649 // First finger down on both window and spy
11650 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011651 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011652 {10, 10}))
11653 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11654 window->consumeMotionDown();
11655 spy->consumeMotionDown();
11656
11657 // Spy window pilfers the pointers.
11658 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11659 window->consumeMotionCancel();
11660
11661 // Second finger down on the window only
11662 const MotionEvent secondFingerDownEvent =
11663 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11664 .displayId(ADISPLAY_ID_DEFAULT)
11665 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011666 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11667 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011668 .build();
11669 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011670 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011671 InputEventInjectionSync::WAIT_FOR_RESULT))
11672 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11673 window->consumeMotionDown();
11674 window->assertNoEvents();
11675
11676 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
11677 spy->consumeMotionMove();
11678 spy->assertNoEvents();
11679}
11680
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011681/**
11682 * A window on the left and a window on the right. Also, a spy window that's above all of the
11683 * windows, and spanning both left and right windows.
11684 * Send simultaneous motion streams from two different devices, one to the left window, and another
11685 * to the right window.
11686 * Pilfer from spy window.
11687 * Check that the pilfering only affects the pointers that are actually being received by the spy.
11688 */
11689TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
11690 sp<FakeWindowHandle> spy = createSpy();
11691 spy->setFrame(Rect(0, 0, 200, 200));
11692 sp<FakeWindowHandle> leftWindow = createForeground();
11693 leftWindow->setFrame(Rect(0, 0, 100, 100));
11694
11695 sp<FakeWindowHandle> rightWindow = createForeground();
11696 rightWindow->setFrame(Rect(100, 0, 200, 100));
11697
11698 constexpr int32_t stylusDeviceId = 1;
11699 constexpr int32_t touchDeviceId = 2;
11700
11701 mDispatcher->onWindowInfosChanged(
11702 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
11703
11704 // Stylus down on left window and spy
11705 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
11706 .deviceId(stylusDeviceId)
11707 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
11708 .build());
11709 leftWindow->consumeMotionEvent(
11710 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11711 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11712
11713 // Finger down on right window and spy - but spy already has stylus
11714 mDispatcher->notifyMotion(
11715 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11716 .deviceId(touchDeviceId)
11717 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
11718 .build());
11719 rightWindow->consumeMotionEvent(
11720 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011721 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011722
11723 // Act: pilfer from spy. Spy is currently receiving touch events.
11724 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011725 leftWindow->consumeMotionEvent(
11726 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011727 rightWindow->consumeMotionEvent(
11728 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
11729
11730 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
11731 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
11732 .deviceId(stylusDeviceId)
11733 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
11734 .build());
11735 mDispatcher->notifyMotion(
11736 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
11737 .deviceId(touchDeviceId)
11738 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
11739 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011740 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011741
11742 spy->assertNoEvents();
11743 leftWindow->assertNoEvents();
11744 rightWindow->assertNoEvents();
11745}
11746
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000011747TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
11748 auto window = createForeground();
11749 auto spy = createSpy();
11750 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
11751
11752 mDispatcher->notifyMotion(
11753 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11754 .deviceId(1)
11755 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
11756 .build());
11757 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11758 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11759
11760 // Pilfer pointers from the spy window should fail.
11761 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
11762 spy->assertNoEvents();
11763 window->assertNoEvents();
11764}
11765
Prabir Pradhand65552b2021-10-07 11:23:50 -070011766class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
11767public:
11768 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
11769 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11770 std::make_shared<FakeApplicationHandle>();
11771 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011772 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11773 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011774 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011775 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011776 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011777 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011778 overlay->setTrustedOverlay(true);
11779
11780 std::shared_ptr<FakeApplicationHandle> application =
11781 std::make_shared<FakeApplicationHandle>();
11782 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011783 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
11784 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011785 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011786 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011787
11788 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011789 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011790 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011791 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011792 return {std::move(overlay), std::move(window)};
11793 }
11794
11795 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011796 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070011797 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000011798 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070011799 }
11800
11801 void sendStylusEvent(int32_t action) {
11802 NotifyMotionArgs motionArgs =
11803 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
11804 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011805 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000011806 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011807 }
11808};
11809
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011810using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
11811
11812TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070011813 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011814 ScopedSilentDeath _silentDeath;
11815
Prabir Pradhand65552b2021-10-07 11:23:50 -070011816 auto [overlay, window] = setupStylusOverlayScenario();
11817 overlay->setTrustedOverlay(false);
11818 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011819 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
11820 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070011821 ".* not a trusted overlay");
11822}
11823
11824TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
11825 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011826 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011827
11828 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11829 overlay->consumeMotionDown();
11830 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11831 overlay->consumeMotionUp();
11832
11833 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11834 window->consumeMotionDown();
11835 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11836 window->consumeMotionUp();
11837
11838 overlay->assertNoEvents();
11839 window->assertNoEvents();
11840}
11841
11842TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
11843 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011844 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011845 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011846
11847 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11848 overlay->consumeMotionDown();
11849 window->consumeMotionDown();
11850 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11851 overlay->consumeMotionUp();
11852 window->consumeMotionUp();
11853
11854 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11855 window->consumeMotionDown();
11856 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11857 window->consumeMotionUp();
11858
11859 overlay->assertNoEvents();
11860 window->assertNoEvents();
11861}
11862
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011863/**
11864 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
11865 * The scenario is as follows:
11866 * - The stylus interceptor overlay is configured as a spy window.
11867 * - The stylus interceptor spy receives the start of a new stylus gesture.
11868 * - It pilfers pointers and then configures itself to no longer be a spy.
11869 * - The stylus interceptor continues to receive the rest of the gesture.
11870 */
11871TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
11872 auto [overlay, window] = setupStylusOverlayScenario();
11873 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011874 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011875
11876 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11877 overlay->consumeMotionDown();
11878 window->consumeMotionDown();
11879
11880 // The interceptor pilfers the pointers.
11881 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
11882 window->consumeMotionCancel();
11883
11884 // The interceptor configures itself so that it is no longer a spy.
11885 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011886 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011887
11888 // It continues to receive the rest of the stylus gesture.
11889 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
11890 overlay->consumeMotionMove();
11891 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11892 overlay->consumeMotionUp();
11893
11894 window->assertNoEvents();
11895}
11896
Prabir Pradhan5735a322022-04-11 17:23:34 +000011897struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011898 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011899 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000011900 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
11901 std::unique_ptr<InputDispatcher>& mDispatcher;
11902
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011903 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000011904 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
11905
11906 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011907 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011908 ADISPLAY_ID_DEFAULT, {100, 200},
11909 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
11910 AMOTION_EVENT_INVALID_CURSOR_POSITION},
11911 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
11912 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
11913 }
11914
11915 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011916 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011917 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000011918 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000011919 mPolicyFlags);
11920 }
11921
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011922 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000011923 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11924 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011925 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11926 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000011927 window->setOwnerInfo(mPid, mUid);
11928 return window;
11929 }
11930};
11931
11932using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
11933
11934TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011935 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011936 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011937 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011938
11939 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11940 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11941 window->consumeMotionDown();
11942
11943 setFocusedWindow(window);
11944 window->consumeFocusEvent(true);
11945
11946 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11947 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11948 window->consumeKeyDown(ADISPLAY_ID_NONE);
11949}
11950
11951TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011952 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011953 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011954 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011955
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011956 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011957 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11958 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11959
11960 setFocusedWindow(window);
11961 window->consumeFocusEvent(true);
11962
11963 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11964 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11965 window->assertNoEvents();
11966}
11967
11968TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011969 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011970 auto window = owner.createWindow("Owned window");
11971 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011972 spy->setSpy(true);
11973 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011974 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011975
11976 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11977 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11978 spy->consumeMotionDown();
11979 window->consumeMotionDown();
11980}
11981
11982TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011983 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011984 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011985
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011986 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011987 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011988 randosSpy->setSpy(true);
11989 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011990 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011991
11992 // The event is targeted at owner's window, so injection should succeed, but the spy should
11993 // not receive the event.
11994 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11995 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11996 randosSpy->assertNoEvents();
11997 window->consumeMotionDown();
11998}
11999
12000TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012001 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012002 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012003
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012004 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012005 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012006 randosSpy->setSpy(true);
12007 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012008 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012009
12010 // A user that has injection permission can inject into any window.
12011 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012012 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000012013 ADISPLAY_ID_DEFAULT));
12014 randosSpy->consumeMotionDown();
12015 window->consumeMotionDown();
12016
12017 setFocusedWindow(randosSpy);
12018 randosSpy->consumeFocusEvent(true);
12019
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012020 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000012021 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
12022 window->assertNoEvents();
12023}
12024
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012025TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012026 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012027 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012028
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012029 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012030 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012031 randosWindow->setFrame(Rect{-10, -10, -5, -5});
12032 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012033 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012034
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012035 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000012036 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12037 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12038 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012039 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000012040}
12041
Prabir Pradhan64f21d22023-11-28 21:19:42 +000012042using InputDispatcherPointerInWindowTest = InputDispatcherTest;
12043
12044TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
12045 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12046
12047 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12048 ADISPLAY_ID_DEFAULT);
12049 left->setFrame(Rect(0, 0, 100, 100));
12050 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12051 "Right Window", ADISPLAY_ID_DEFAULT);
12052 right->setFrame(Rect(100, 0, 200, 100));
12053 sp<FakeWindowHandle> spy =
12054 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
12055 spy->setFrame(Rect(0, 0, 200, 100));
12056 spy->setTrustedOverlay(true);
12057 spy->setSpy(true);
12058
12059 mDispatcher->onWindowInfosChanged(
12060 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
12061
12062 // Hover into the left window.
12063 mDispatcher->notifyMotion(
12064 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
12065 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
12066 .build());
12067
12068 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12069 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12070
12071 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12072 /*pointerId=*/0));
12073 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12074 /*pointerId=*/0));
12075 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12076 /*pointerId=*/0));
12077
12078 // Hover move to the right window.
12079 mDispatcher->notifyMotion(
12080 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
12081 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
12082 .build());
12083
12084 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12085 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12086 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
12087
12088 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12089 /*pointerId=*/0));
12090 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12091 /*pointerId=*/0));
12092 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12093 /*pointerId=*/0));
12094
12095 // Stop hovering.
12096 mDispatcher->notifyMotion(
12097 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
12098 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
12099 .build());
12100
12101 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12102 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12103
12104 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12105 /*pointerId=*/0));
12106 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12107 /*pointerId=*/0));
12108 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12109 /*pointerId=*/0));
12110}
12111
12112TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
12113 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12114
12115 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12116 ADISPLAY_ID_DEFAULT);
12117 left->setFrame(Rect(0, 0, 100, 100));
12118 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12119 "Right Window", ADISPLAY_ID_DEFAULT);
12120 right->setFrame(Rect(100, 0, 200, 100));
12121 sp<FakeWindowHandle> spy =
12122 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
12123 spy->setFrame(Rect(0, 0, 200, 100));
12124 spy->setTrustedOverlay(true);
12125 spy->setSpy(true);
12126
12127 mDispatcher->onWindowInfosChanged(
12128 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
12129
12130 // First pointer down on left window.
12131 mDispatcher->notifyMotion(
12132 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12133 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12134 .build());
12135
12136 left->consumeMotionDown();
12137 spy->consumeMotionDown();
12138
12139 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12140 /*pointerId=*/0));
12141 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12142 /*pointerId=*/0));
12143 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12144 /*pointerId=*/0));
12145
12146 // Second pointer down on right window.
12147 mDispatcher->notifyMotion(
12148 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12149 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12150 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
12151 .build());
12152
12153 left->consumeMotionMove();
12154 right->consumeMotionDown();
12155 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
12156
12157 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12158 /*pointerId=*/0));
12159 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12160 /*pointerId=*/0));
12161 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12162 /*pointerId=*/0));
12163 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12164 /*pointerId=*/1));
12165 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12166 /*pointerId=*/1));
12167 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12168 /*pointerId=*/1));
12169
12170 // Second pointer up.
12171 mDispatcher->notifyMotion(
12172 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
12173 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12174 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
12175 .build());
12176
12177 left->consumeMotionMove();
12178 right->consumeMotionUp();
12179 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
12180
12181 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12182 /*pointerId=*/0));
12183 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12184 /*pointerId=*/0));
12185 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12186 /*pointerId=*/0));
12187 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12188 /*pointerId=*/1));
12189 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12190 /*pointerId=*/1));
12191 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12192 /*pointerId=*/1));
12193
12194 // First pointer up.
12195 mDispatcher->notifyMotion(
12196 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
12197 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12198 .build());
12199
12200 left->consumeMotionUp();
12201 spy->consumeMotionUp();
12202
12203 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12204 /*pointerId=*/0));
12205 ASSERT_FALSE(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
12211TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
12212 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12213
12214 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12215 ADISPLAY_ID_DEFAULT);
12216 left->setFrame(Rect(0, 0, 100, 100));
12217 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12218 "Right Window", ADISPLAY_ID_DEFAULT);
12219 right->setFrame(Rect(100, 0, 200, 100));
12220
12221 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
12222
12223 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->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
12228 // Hover move into the window.
12229 mDispatcher->notifyMotion(
12230 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12231 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
12232 .rawXCursorPosition(50)
12233 .rawYCursorPosition(50)
12234 .deviceId(DEVICE_ID)
12235 .build());
12236
12237 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12238
12239 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12240 /*pointerId=*/0));
12241
12242 // Move the mouse with another device. This cancels the hovering pointer from the first device.
12243 mDispatcher->notifyMotion(
12244 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12245 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
12246 .rawXCursorPosition(51)
12247 .rawYCursorPosition(50)
12248 .deviceId(SECOND_DEVICE_ID)
12249 .build());
12250
12251 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12252 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12253
12254 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
12255 // a HOVER_EXIT from the first device.
12256 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12257 /*pointerId=*/0));
12258 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
12259 SECOND_DEVICE_ID,
12260 /*pointerId=*/0));
12261
12262 // Move the mouse outside the window. Document the current behavior, where the window does not
12263 // receive HOVER_EXIT even though the mouse left the window.
12264 mDispatcher->notifyMotion(
12265 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12266 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
12267 .rawXCursorPosition(150)
12268 .rawYCursorPosition(50)
12269 .deviceId(SECOND_DEVICE_ID)
12270 .build());
12271
12272 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12273 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12274 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12275 /*pointerId=*/0));
12276 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
12277 SECOND_DEVICE_ID,
12278 /*pointerId=*/0));
12279}
12280
Garfield Tane84e6f92019-08-29 17:28:41 -070012281} // namespace android::inputdispatcher