blob: 55d5f1303f7443bc241e135365e4d4d29a728457 [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 Pradhandc3a2ad2024-02-05 19:03:51 +000020#include "FakeInputTracingBackend.h"
Prabir Pradhane3b28dd2023-10-06 04:19:29 +000021#include "TestEventMatchers.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080022
Cody Heiner166a5af2023-07-07 12:25:00 -070023#include <NotifyArgsBuilders.h>
Prabir Pradhan5893d362023-11-17 04:30:40 +000024#include <android-base/logging.h>
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070025#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080026#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080027#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070028#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070029#include <binder/Binder.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000030#include <com_android_input_flags.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000031#include <fcntl.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000032#include <flag_macros.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080033#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080034#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100035#include <input/Input.h>
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070036#include <input/PrintTools.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080037#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080038#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100039
Garfield Tan1c7bc862020-01-28 13:24:04 -080040#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080041#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070042#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080043#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080044#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080045
Garfield Tan1c7bc862020-01-28 13:24:04 -080046using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050047using android::gui::FocusRequest;
48using android::gui::TouchOcclusionMode;
49using android::gui::WindowInfo;
50using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080051using android::os::InputEventInjectionResult;
52using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080053
Garfield Tane84e6f92019-08-29 17:28:41 -070054namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080055
Dominik Laskowski2f01d772022-03-23 16:01:29 -070056using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080057using testing::AllOf;
Prabir Pradhan5893d362023-11-17 04:30:40 +000058using testing::Not;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070059
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070060namespace {
61
Michael Wrightd02c5b62014-02-10 15:10:22 -080062// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000063static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080064
65// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000066static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080067static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080068
Jeff Brownf086ddb2014-02-11 14:28:48 -080069// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000070static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
71static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080072
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000073// Ensure common actions are interchangeable between keys and motions for convenience.
74static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
75static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080076static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
77static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
78static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
79static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070080static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080081static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070082static constexpr int32_t ACTION_SCROLL = AMOTION_EVENT_ACTION_SCROLL;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080083static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080084static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080085/**
86 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
87 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
88 * index 0) is the new pointer going down. The same pointer could have been placed at a different
89 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
90 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
91 * pointer id=0 leaves but the pointer id=1 remains.
92 */
93static constexpr int32_t POINTER_0_DOWN =
94 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080095static constexpr int32_t POINTER_1_DOWN =
96 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000097static constexpr int32_t POINTER_2_DOWN =
98 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000099static constexpr int32_t POINTER_3_DOWN =
100 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +0000101static constexpr int32_t POINTER_0_UP =
102 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800103static constexpr int32_t POINTER_1_UP =
104 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +0000105static constexpr int32_t POINTER_2_UP =
106 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800107
Antonio Kantek15beb512022-06-13 22:35:41 +0000108// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000109static constexpr gui::Pid WINDOW_PID{999};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000110static constexpr gui::Uid WINDOW_UID{1001};
Prabir Pradhan5735a322022-04-11 17:23:34 +0000111
Antonio Kantek15beb512022-06-13 22:35:41 +0000112// The default pid and uid for the windows created on the secondary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000113static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000114static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000115
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000116// An arbitrary pid of the gesture monitor window
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000117static constexpr gui::Pid MONITOR_PID{2001};
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000118
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700119/**
120 * If we expect to receive the event, the timeout can be made very long. When the test are running
121 * correctly, we will actually never wait until the end of the timeout because the wait will end
122 * when the event comes in. Still, this value shouldn't be infinite. During development, a local
123 * change may cause the test to fail. This timeout should be short enough to not annoy so that the
124 * developer can see the failure quickly (on human scale).
125 */
126static constexpr std::chrono::duration CONSUME_TIMEOUT_EVENT_EXPECTED = 1000ms;
127/**
128 * When no event is expected, we can have a very short timeout. A large value here would slow down
129 * the tests. In the unlikely event of system being too slow, the event may still be present but the
130 * timeout would complete before it is consumed. This would result in test flakiness. If this
131 * occurs, the flakiness rate would be high. Since the flakes are treated with high priority, this
132 * would get noticed and addressed quickly.
133 */
134static constexpr std::chrono::duration CONSUME_TIMEOUT_NO_EVENT_EXPECTED = 10ms;
135
Arthur Hungc539dbb2022-12-08 07:45:36 +0000136static constexpr int expectedWallpaperFlags =
137 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
138
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800139using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
140
Gang Wang342c9272020-01-13 13:15:04 -0500141/**
142 * Return a DOWN key event with KEYCODE_A.
143 */
144static KeyEvent getTestKeyEvent() {
145 KeyEvent event;
146
Garfield Tanfbe732e2020-01-24 11:26:14 -0800147 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
148 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
149 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500150 return event;
151}
152
Michael Wrightd02c5b62014-02-10 15:10:22 -0800153// --- FakeInputDispatcherPolicy ---
154
155class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000156 struct AnrResult {
157 sp<IBinder> token{};
Prabir Pradhanfc364722024-02-08 17:51:20 +0000158 std::optional<gui::Pid> pid{};
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000159 };
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800160 /* Stores data about a user-activity-poke event from the dispatcher. */
161 struct UserActivityPokeEvent {
162 nsecs_t eventTime;
163 int32_t eventType;
164 int32_t displayId;
165
166 bool operator==(const UserActivityPokeEvent& rhs) const = default;
167
168 friend std::ostream& operator<<(std::ostream& os, const UserActivityPokeEvent& ev) {
169 os << "UserActivityPokeEvent[time=" << ev.eventTime << ", eventType=" << ev.eventType
170 << ", displayId=" << ev.displayId << "]";
171 return os;
172 }
173 };
Prabir Pradhanedd96402022-02-15 01:46:16 -0800174
Michael Wrightd02c5b62014-02-10 15:10:22 -0800175public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000176 FakeInputDispatcherPolicy() = default;
177 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800178
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800179 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700180 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700181 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700182 EXPECT_EQ(event.getDisplayId(), args.displayId);
183
184 const auto& keyEvent = static_cast<const KeyEvent&>(event);
185 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
186 EXPECT_EQ(keyEvent.getAction(), args.action);
187 });
Jackal Guof9696682018-10-05 12:23:23 +0800188 }
189
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700190 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
191 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700192 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700193 EXPECT_EQ(event.getDisplayId(), args.displayId);
194
195 const auto& motionEvent = static_cast<const MotionEvent&>(event);
196 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
197 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000198 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
199 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
200 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
201 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700202 });
Jackal Guof9696682018-10-05 12:23:23 +0800203 }
204
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700205 void assertFilterInputEventWasNotCalled() {
206 std::scoped_lock lock(mLock);
207 ASSERT_EQ(nullptr, mFilteredEvent);
208 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800209
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800210 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700211 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800212 ASSERT_TRUE(mConfigurationChangedTime)
213 << "Timed out waiting for configuration changed call";
214 ASSERT_EQ(*mConfigurationChangedTime, when);
215 mConfigurationChangedTime = std::nullopt;
216 }
217
218 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700219 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800220 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800221 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800222 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
223 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
224 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
225 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
226 mLastNotifySwitch = std::nullopt;
227 }
228
chaviwfd6d3512019-03-25 13:23:49 -0700229 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700230 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800231 ASSERT_EQ(touchedToken, mOnPointerDownToken);
232 mOnPointerDownToken.clear();
233 }
234
235 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700236 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800237 ASSERT_TRUE(mOnPointerDownToken == nullptr)
238 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700239 }
240
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700241 // This function must be called soon after the expected ANR timer starts,
242 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500243 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700244 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500245 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800246 std::unique_lock lock(mLock);
247 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500248 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800249 ASSERT_NO_FATAL_FAILURE(
250 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500251 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700252 }
253
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000254 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800255 const sp<WindowInfoHandle>& window) {
256 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
257 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
258 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500259 }
260
Prabir Pradhanedd96402022-02-15 01:46:16 -0800261 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
262 const sp<IBinder>& expectedToken,
Prabir Pradhanfc364722024-02-08 17:51:20 +0000263 std::optional<gui::Pid> expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800264 std::unique_lock lock(mLock);
265 android::base::ScopedLockAssertion assumeLocked(mLock);
266 AnrResult result;
267 ASSERT_NO_FATAL_FAILURE(result =
268 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000269 ASSERT_EQ(expectedToken, result.token);
270 ASSERT_EQ(expectedPid, result.pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500271 }
272
Prabir Pradhanedd96402022-02-15 01:46:16 -0800273 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000274 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500275 std::unique_lock lock(mLock);
276 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800277 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
278 const auto& [token, _] = result;
279 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000280 }
281
Prabir Pradhanedd96402022-02-15 01:46:16 -0800282 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
Prabir Pradhanfc364722024-02-08 17:51:20 +0000283 std::optional<gui::Pid> expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800284 std::unique_lock lock(mLock);
285 android::base::ScopedLockAssertion assumeLocked(mLock);
286 AnrResult result;
287 ASSERT_NO_FATAL_FAILURE(
288 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000289 ASSERT_EQ(expectedToken, result.token);
290 ASSERT_EQ(expectedPid, result.pid);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800291 }
292
293 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000294 sp<IBinder> getResponsiveWindowToken() {
295 std::unique_lock lock(mLock);
296 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800297 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
298 const auto& [token, _] = result;
299 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700300 }
301
302 void assertNotifyAnrWasNotCalled() {
303 std::scoped_lock lock(mLock);
304 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800305 ASSERT_TRUE(mAnrWindows.empty());
306 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500307 << "ANR was not called, but please also consume the 'connection is responsive' "
308 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700309 }
310
Hiroki Sato25040232024-02-22 17:21:22 +0900311 PointerCaptureRequest assertSetPointerCaptureCalled(const sp<WindowInfoHandle>& window,
312 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800313 std::unique_lock lock(mLock);
314 base::ScopedLockAssertion assumeLocked(mLock);
315
Hiroki Sato25040232024-02-22 17:21:22 +0900316 if (!mPointerCaptureChangedCondition
317 .wait_for(lock, 100ms, [this, enabled, window]() REQUIRES(mLock) {
318 if (enabled) {
319 return mPointerCaptureRequest->isEnable() &&
320 mPointerCaptureRequest->window == window->getToken();
321 } else {
322 return !mPointerCaptureRequest->isEnable();
323 }
324 })) {
325 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << window->getName() << ", "
326 << enabled << ") to be called.";
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000327 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800328 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000329 auto request = *mPointerCaptureRequest;
330 mPointerCaptureRequest.reset();
331 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800332 }
333
334 void assertSetPointerCaptureNotCalled() {
335 std::unique_lock lock(mLock);
336 base::ScopedLockAssertion assumeLocked(mLock);
337
338 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000339 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800340 "enabled = "
Hiroki Sato25040232024-02-22 17:21:22 +0900341 << std::to_string(mPointerCaptureRequest->isEnable());
Prabir Pradhan99987712020-11-10 18:43:05 -0800342 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000343 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800344 }
345
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -0700346 void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
347 const sp<IBinder>& targetToken) {
348 dispatcher.waitForIdle();
arthurhungf452d0b2021-01-06 00:19:52 +0800349 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800350 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800351 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800352 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800353 }
354
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800355 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
356 std::unique_lock lock(mLock);
357 base::ScopedLockAssertion assumeLocked(mLock);
358 std::optional<sp<IBinder>> receivedToken =
359 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
360 mNotifyInputChannelBroken);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000361 ASSERT_TRUE(receivedToken.has_value()) << "Did not receive the broken channel token";
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800362 ASSERT_EQ(token, *receivedToken);
363 }
364
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800365 /**
366 * Set policy timeout. A value of zero means next key will not be intercepted.
367 */
368 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
369 mInterceptKeyTimeout = timeout;
370 }
371
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -0800372 std::chrono::nanoseconds getKeyWaitingForEventsTimeout() override { return 500ms; }
373
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700374 void setStaleEventTimeout(std::chrono::nanoseconds timeout) { mStaleEventTimeout = timeout; }
375
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800376 void assertUserActivityNotPoked() {
377 std::unique_lock lock(mLock);
378 base::ScopedLockAssertion assumeLocked(mLock);
379
380 std::optional<UserActivityPokeEvent> pokeEvent =
381 getItemFromStorageLockedInterruptible(500ms, mUserActivityPokeEvents, lock,
382 mNotifyUserActivity);
383
384 ASSERT_FALSE(pokeEvent) << "Expected user activity not to have been poked";
Josep del Riob3981622023-04-18 15:49:45 +0000385 }
386
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800387 /**
388 * Asserts that a user activity poke has happened. The earliest recorded poke event will be
389 * cleared after this call.
390 *
391 * If an expected UserActivityPokeEvent is provided, asserts that the given event is the
392 * earliest recorded poke event.
393 */
394 void assertUserActivityPoked(std::optional<UserActivityPokeEvent> expectedPokeEvent = {}) {
395 std::unique_lock lock(mLock);
396 base::ScopedLockAssertion assumeLocked(mLock);
397
398 std::optional<UserActivityPokeEvent> pokeEvent =
399 getItemFromStorageLockedInterruptible(500ms, mUserActivityPokeEvents, lock,
400 mNotifyUserActivity);
401 ASSERT_TRUE(pokeEvent) << "Expected a user poke event";
402
403 if (expectedPokeEvent) {
404 ASSERT_EQ(expectedPokeEvent, *pokeEvent);
405 }
Josep del Riob3981622023-04-18 15:49:45 +0000406 }
407
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000408 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000409 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
410 }
411
412 void assertNotifyDeviceInteractionWasNotCalled() {
413 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
414 }
415
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000416 void setUnhandledKeyHandler(std::function<std::optional<KeyEvent>(const KeyEvent&)> handler) {
417 std::scoped_lock lock(mLock);
418 mUnhandledKeyHandler = handler;
419 }
420
421 void assertUnhandledKeyReported(int32_t keycode) {
422 std::unique_lock lock(mLock);
423 base::ScopedLockAssertion assumeLocked(mLock);
424 std::optional<int32_t> unhandledKeycode =
425 getItemFromStorageLockedInterruptible(100ms, mReportedUnhandledKeycodes, lock,
426 mNotifyUnhandledKey);
427 ASSERT_TRUE(unhandledKeycode) << "Expected unhandled key to be reported";
428 ASSERT_EQ(unhandledKeycode, keycode);
429 }
430
431 void assertUnhandledKeyNotReported() {
432 std::unique_lock lock(mLock);
433 base::ScopedLockAssertion assumeLocked(mLock);
434 std::optional<int32_t> unhandledKeycode =
435 getItemFromStorageLockedInterruptible(10ms, mReportedUnhandledKeycodes, lock,
436 mNotifyUnhandledKey);
437 ASSERT_FALSE(unhandledKeycode) << "Expected unhandled key NOT to be reported";
438 }
439
Michael Wrightd02c5b62014-02-10 15:10:22 -0800440private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700441 std::mutex mLock;
442 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
443 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
444 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
445 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800446
Prabir Pradhan99987712020-11-10 18:43:05 -0800447 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000448
449 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800450
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700451 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700452 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800453 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
454 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700455 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800456 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
457 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700458
arthurhungf452d0b2021-01-06 00:19:52 +0800459 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800460 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800461
462 std::condition_variable mNotifyUserActivity;
463 std::queue<UserActivityPokeEvent> mUserActivityPokeEvents;
arthurhungf452d0b2021-01-06 00:19:52 +0800464
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800465 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
466
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700467 std::chrono::nanoseconds mStaleEventTimeout = 1000ms;
468
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000469 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000470
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000471 std::condition_variable mNotifyUnhandledKey;
472 std::queue<int32_t> mReportedUnhandledKeycodes GUARDED_BY(mLock);
473 std::function<std::optional<KeyEvent>(const KeyEvent&)> mUnhandledKeyHandler GUARDED_BY(mLock);
474
Prabir Pradhanedd96402022-02-15 01:46:16 -0800475 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
476 // for a specific container to become non-empty. When the container is non-empty, return the
477 // first entry from the container and erase it.
478 template <class T>
479 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
480 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
481 // If there is an ANR, Dispatcher won't be idle because there are still events
482 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
483 // before checking if ANR was called.
484 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
485 // to provide it some time to act. 100ms seems reasonable.
486 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
487 const std::chrono::time_point start = std::chrono::steady_clock::now();
488 std::optional<T> token =
489 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
490 if (!token.has_value()) {
491 ADD_FAILURE() << "Did not receive the ANR callback";
492 return {};
493 }
494
495 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
496 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
497 // the dispatcher started counting before this function was called
498 if (std::chrono::abs(timeout - waited) > 100ms) {
499 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
500 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
501 << "ms, but waited "
502 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
503 << "ms instead";
504 }
505 return *token;
506 }
507
508 template <class T>
509 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
510 std::queue<T>& storage,
511 std::unique_lock<std::mutex>& lock,
512 std::condition_variable& condition)
513 REQUIRES(mLock) {
514 condition.wait_for(lock, timeout,
515 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
516 if (storage.empty()) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800517 return std::nullopt;
518 }
519 T item = storage.front();
520 storage.pop();
521 return std::make_optional(item);
522 }
523
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600524 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700525 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800526 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800527 }
528
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000529 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800530 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700531 std::scoped_lock lock(mLock);
Prabir Pradhanfc364722024-02-08 17:51:20 +0000532 mAnrWindows.push({connectionToken, pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700533 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500534 }
535
Prabir Pradhanedd96402022-02-15 01:46:16 -0800536 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000537 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500538 std::scoped_lock lock(mLock);
Prabir Pradhanfc364722024-02-08 17:51:20 +0000539 mResponsiveWindows.push({connectionToken, pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500540 mNotifyAnr.notify_all();
541 }
542
543 void notifyNoFocusedWindowAnr(
544 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
545 std::scoped_lock lock(mLock);
546 mAnrApplications.push(applicationHandle);
547 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800548 }
549
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800550 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
551 std::scoped_lock lock(mLock);
552 mBrokenInputChannels.push(connectionToken);
553 mNotifyInputChannelBroken.notify_all();
554 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800555
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600556 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700557
Chris Yef59a2f42020-10-16 12:55:26 -0700558 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
559 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
560 const std::vector<float>& values) override {}
561
562 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
563 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000564
Chris Yefb552902021-02-03 17:18:37 -0800565 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
566
Prabir Pradhana41d2442023-04-20 21:30:40 +0000567 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700568 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000569 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700570 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000571 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
572 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800573 break;
574 }
575
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700576 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000577 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
578 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800579 break;
580 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700581 default: {
582 ADD_FAILURE() << "Should only filter keys or motions";
583 break;
584 }
Jackal Guof9696682018-10-05 12:23:23 +0800585 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800586 return true;
587 }
588
Prabir Pradhana41d2442023-04-20 21:30:40 +0000589 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
590 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800591 // Clear intercept state when we handled the event.
592 mInterceptKeyTimeout = 0ms;
593 }
594 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800595
Yeabkal Wubshit88a90412023-12-21 18:23:04 -0800596 void interceptMotionBeforeQueueing(int32_t, uint32_t, int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800597
Prabir Pradhana41d2442023-04-20 21:30:40 +0000598 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800599 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
600 // Clear intercept state so we could dispatch the event in next wake.
601 mInterceptKeyTimeout = 0ms;
602 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800603 }
604
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000605 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent& event,
Prabir Pradhana41d2442023-04-20 21:30:40 +0000606 uint32_t) override {
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000607 std::scoped_lock lock(mLock);
608 mReportedUnhandledKeycodes.emplace(event.getKeyCode());
609 mNotifyUnhandledKey.notify_all();
610 return mUnhandledKeyHandler != nullptr ? mUnhandledKeyHandler(event) : std::nullopt;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800611 }
612
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600613 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
614 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700615 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800616 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
617 * essentially a passthrough for notifySwitch.
618 */
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000619 mLastNotifySwitch =
620 NotifySwitchArgs(InputEvent::nextId(), when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800621 }
622
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800623 void pokeUserActivity(nsecs_t eventTime, int32_t eventType, int32_t displayId) override {
Josep del Riob3981622023-04-18 15:49:45 +0000624 std::scoped_lock lock(mLock);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800625 mNotifyUserActivity.notify_all();
626 mUserActivityPokeEvents.push({eventTime, eventType, displayId});
Josep del Riob3981622023-04-18 15:49:45 +0000627 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800628
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700629 bool isStaleEvent(nsecs_t currentTime, nsecs_t eventTime) override {
630 return std::chrono::nanoseconds(currentTime - eventTime) >= mStaleEventTimeout;
631 }
632
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600633 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700634 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700635 mOnPointerDownToken = newToken;
636 }
637
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000638 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800639 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000640 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800641 mPointerCaptureChangedCondition.notify_all();
642 }
643
arthurhungf452d0b2021-01-06 00:19:52 +0800644 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
645 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800646 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800647 mDropTargetWindowToken = token;
648 }
649
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000650 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000651 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000652 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
653 }
654
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700655 void assertFilterInputEventWasCalledInternal(
656 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700657 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800658 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700659 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800660 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800661 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800662};
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700663} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800664
Michael Wrightd02c5b62014-02-10 15:10:22 -0800665// --- InputDispatcherTest ---
666
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000667// The trace is a global variable for now, to avoid having to pass it into all of the
668// FakeWindowHandles created throughout the tests.
669// TODO(b/210460522): Update the tests to avoid the need to have the trace be a global variable.
670static std::shared_ptr<VerifyingTrace> gVerifyingTrace = std::make_shared<VerifyingTrace>();
671
Michael Wrightd02c5b62014-02-10 15:10:22 -0800672class InputDispatcherTest : public testing::Test {
673protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000674 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700675 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800676
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000677 void SetUp() override {
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000678 gVerifyingTrace->reset();
Prabir Pradhana41d2442023-04-20 21:30:40 +0000679 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000680 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy,
681 std::make_unique<FakeInputTracingBackend>(
682 gVerifyingTrace));
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700683
Harry Cutts101ee9b2023-07-06 18:04:14 +0000684 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000685 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700686 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800687 }
688
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000689 void TearDown() override {
Prabir Pradhan0eaf1402024-02-05 22:43:04 +0000690 ASSERT_NO_FATAL_FAILURE(gVerifyingTrace->verifyExpectedEventsTraced());
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700691 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000692 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700693 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800694 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700695
696 /**
697 * Used for debugging when writing the test
698 */
699 void dumpDispatcherState() {
700 std::string dump;
701 mDispatcher->dump(dump);
702 std::stringstream ss(dump);
703 std::string to;
704
705 while (std::getline(ss, to, '\n')) {
706 ALOGE("%s", to.c_str());
707 }
708 }
Vishnu Nair958da932020-08-21 17:12:37 -0700709
Chavi Weingarten847e8512023-03-29 00:26:09 +0000710 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700711 FocusRequest request;
712 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000713 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700714 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
715 request.displayId = window->getInfo()->displayId;
716 mDispatcher->setFocusedWindow(request);
717 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800718};
719
Michael Wrightd02c5b62014-02-10 15:10:22 -0800720TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
721 KeyEvent event;
722
723 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800724 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
725 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000726 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600727 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800728 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000729 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000730 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800731 << "Should reject key events with undefined action.";
732
733 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800734 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
735 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600736 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800737 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000738 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000739 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800740 << "Should reject key events with ACTION_MULTIPLE.";
741}
742
743TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
744 MotionEvent event;
745 PointerProperties pointerProperties[MAX_POINTERS + 1];
746 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800747 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800748 pointerProperties[i].clear();
749 pointerProperties[i].id = i;
750 pointerCoords[i].clear();
751 }
752
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800753 // Some constants commonly used below
754 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
755 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
756 constexpr int32_t metaState = AMETA_NONE;
757 constexpr MotionClassification classification = MotionClassification::NONE;
758
chaviw9eaa22c2020-07-01 16:21:27 -0700759 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800760 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800761 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000762 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700763 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700764 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
765 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000766 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800767 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000768 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000769 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800770 << "Should reject motion events with undefined action.";
771
772 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800773 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800774 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
775 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
776 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
777 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000778 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800779 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000780 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000781 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800782 << "Should reject motion events with pointer down index too large.";
783
Garfield Tanfbe732e2020-01-24 11:26:14 -0800784 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700785 AMOTION_EVENT_ACTION_POINTER_DOWN |
786 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700787 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
788 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700789 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000790 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800791 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000792 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000793 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800794 << "Should reject motion events with pointer down index too small.";
795
796 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800797 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800798 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
799 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
800 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
801 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000802 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800803 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000804 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000805 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800806 << "Should reject motion events with pointer up index too large.";
807
Garfield Tanfbe732e2020-01-24 11:26:14 -0800808 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700809 AMOTION_EVENT_ACTION_POINTER_UP |
810 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700811 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
812 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700813 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000814 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800815 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000816 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000817 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800818 << "Should reject motion events with pointer up index too small.";
819
820 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800821 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
822 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700823 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700824 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
825 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000826 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800827 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000828 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000829 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800830 << "Should reject motion events with 0 pointers.";
831
Garfield Tanfbe732e2020-01-24 11:26:14 -0800832 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
833 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700834 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700835 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
836 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000837 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800838 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000839 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000840 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800841 << "Should reject motion events with more than MAX_POINTERS pointers.";
842
843 // Rejects motion events with invalid pointer ids.
844 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800845 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
846 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700847 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700848 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
849 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000850 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800851 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000852 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000853 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800854 << "Should reject motion events with pointer ids less than 0.";
855
856 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800857 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
858 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700859 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700860 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
861 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000862 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800863 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000864 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000865 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800866 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
867
868 // Rejects motion events with duplicate pointer ids.
869 pointerProperties[0].id = 1;
870 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800871 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
872 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700873 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700874 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
875 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000876 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800877 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000878 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000879 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800880 << "Should reject motion events with duplicate pointer ids.";
881}
882
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800883/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
884
885TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
886 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000887 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800888 ASSERT_TRUE(mDispatcher->waitForIdle());
889
890 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
891}
892
893TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000894 NotifySwitchArgs args(InputEvent::nextId(), /*eventTime=*/20, /*policyFlags=*/0,
895 /*switchValues=*/1,
Harry Cutts33476232023-01-30 19:57:29 +0000896 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000897 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800898
899 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
900 args.policyFlags |= POLICY_FLAG_TRUSTED;
901 mFakePolicy->assertNotifySwitchWasCalled(args);
902}
903
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700904namespace {
905
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700906static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700907// Default input dispatching timeout if there is no focused application or paused window
908// from which to determine an appropriate dispatching timeout.
909static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
910 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
911 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800912
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800913class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800914public:
Garfield Tan15601662020-09-22 15:32:38 -0700915 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700916 : mConsumer(std::move(clientChannel)), mName(name) {}
chaviwd1c23182019-12-20 18:44:56 -0800917
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800918 std::unique_ptr<InputEvent> consume(std::chrono::milliseconds timeout, bool handled = false) {
919 auto [consumeSeq, event] = receiveEvent(timeout);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700920 if (!consumeSeq) {
921 return nullptr;
922 }
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000923 finishEvent(*consumeSeq, handled);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800924 return std::move(event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700925 }
926
927 /**
928 * Receive an event without acknowledging it.
929 * Return the sequence number that could later be used to send finished signal.
930 */
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800931 std::pair<std::optional<uint32_t>, std::unique_ptr<InputEvent>> receiveEvent(
932 std::chrono::milliseconds timeout) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800933 uint32_t consumeSeq;
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800934 std::unique_ptr<InputEvent> event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800935
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800936 std::chrono::time_point start = std::chrono::steady_clock::now();
937 status_t status = WOULD_BLOCK;
938 while (status == WOULD_BLOCK) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800939 InputEvent* rawEventPtr = nullptr;
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700940 status = mConsumer.consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800941 &rawEventPtr);
942 event = std::unique_ptr<InputEvent>(rawEventPtr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800943 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700944 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800945 break;
946 }
947 }
948
949 if (status == WOULD_BLOCK) {
950 // Just means there's no event available.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800951 return std::make_pair(std::nullopt, nullptr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800952 }
953
954 if (status != OK) {
955 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800956 return std::make_pair(std::nullopt, nullptr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800957 }
958 if (event == nullptr) {
959 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800960 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800961 return std::make_pair(consumeSeq, std::move(event));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700962 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800963
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700964 /**
965 * To be used together with "receiveEvent" to complete the consumption of an event.
966 */
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000967 void finishEvent(uint32_t consumeSeq, bool handled = true) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700968 const status_t status = mConsumer.sendFinishedSignal(consumeSeq, handled);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700969 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800970 }
971
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000972 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700973 const status_t status = mConsumer.sendTimeline(inputEventId, timeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000974 ASSERT_EQ(OK, status);
975 }
976
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700977 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000978 std::optional<int32_t> expectedDisplayId,
979 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800980 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800981
982 ASSERT_NE(nullptr, event) << mName.c_str()
983 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800984 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700985 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
986 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800987
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000988 if (expectedDisplayId.has_value()) {
989 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
990 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800991
Tiger Huang8664f8c2018-10-11 19:14:35 +0800992 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700993 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800994 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700995 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000996 if (expectedFlags.has_value()) {
997 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
998 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800999 break;
1000 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001001 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001002 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -07001003 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001004 if (expectedFlags.has_value()) {
1005 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
1006 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001007 break;
1008 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001009 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001010 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
1011 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001012 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -08001013 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
1014 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001015 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001016 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
1017 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001018 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +08001019 FAIL() << "Use 'consumeDragEvent' for DRAG events";
1020 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001021 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001022 }
1023
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001024 std::unique_ptr<MotionEvent> consumeMotion() {
1025 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001026
1027 if (event == nullptr) {
1028 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
1029 return nullptr;
1030 }
1031
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001032 if (event->getType() != InputEventType::MOTION) {
1033 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001034 return nullptr;
1035 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001036 return std::unique_ptr<MotionEvent>(static_cast<MotionEvent*>(event.release()));
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001037 }
1038
1039 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001040 std::unique_ptr<MotionEvent> motionEvent = consumeMotion();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001041 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1042 ASSERT_THAT(*motionEvent, matcher);
1043 }
1044
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001045 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001046 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001047 ASSERT_NE(nullptr, event) << mName.c_str()
1048 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001049 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1050 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001051
1052 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1053 << mName.c_str() << ": event displayId should always be NONE.";
1054
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001055 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1056 EXPECT_EQ(hasFocus, focusEvent.getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001057 }
1058
Prabir Pradhan99987712020-11-10 18:43:05 -08001059 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001060 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -08001061 ASSERT_NE(nullptr, event) << mName.c_str()
1062 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001063 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1064 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001065
1066 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1067 << mName.c_str() << ": event displayId should always be NONE.";
1068
1069 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1070 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1071 }
1072
arthurhungb89ccb02020-12-30 16:19:01 +08001073 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001074 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +08001075 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::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001078
1079 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1080 << mName.c_str() << ": event displayId should always be NONE.";
1081
1082 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1083 EXPECT_EQ(isExiting, dragEvent.isExiting());
1084 EXPECT_EQ(x, dragEvent.getX());
1085 EXPECT_EQ(y, dragEvent.getY());
1086 }
1087
Antonio Kantekf16f2832021-09-28 04:39:20 +00001088 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001089 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +00001090 ASSERT_NE(nullptr, event) << mName.c_str()
1091 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001092 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1093 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001094
1095 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1096 << mName.c_str() << ": event displayId should always be NONE.";
1097 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1098 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1099 }
1100
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001101 void assertNoEvents(std::chrono::milliseconds timeout) {
1102 std::unique_ptr<InputEvent> event = consume(timeout);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001103 if (event == nullptr) {
1104 return;
1105 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001106 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001107 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001108 ADD_FAILURE() << "Received key event " << keyEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001109 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001110 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001111 ADD_FAILURE() << "Received motion event " << motionEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001112 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001113 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1114 ADD_FAILURE() << "Received focus event, hasFocus = "
1115 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001116 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001117 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1118 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1119 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001120 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001121 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1122 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1123 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001124 }
1125 FAIL() << mName.c_str()
1126 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001127 }
1128
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001129 sp<IBinder> getToken() { return mConsumer.getChannel()->getConnectionToken(); }
chaviwd1c23182019-12-20 18:44:56 -08001130
Siarhei Vishniakou8d660132024-01-11 16:48:44 -08001131 int getChannelFd() { return mConsumer.getChannel()->getFd(); }
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001132
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001133private:
1134 InputConsumer mConsumer;
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001135 DynamicInputEventFactory mEventFactory;
chaviwd1c23182019-12-20 18:44:56 -08001136
1137 std::string mName;
1138};
1139
chaviw3277faf2021-05-19 16:45:23 -05001140class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001141public:
1142 static const int32_t WIDTH = 600;
1143 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001144
Chris Yea209fde2020-07-22 13:54:51 -07001145 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001146 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001147 int32_t displayId, bool createInputChannel = true)
chaviwd1c23182019-12-20 18:44:56 -08001148 : mName(name) {
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001149 sp<IBinder> token;
1150 if (createInputChannel) {
Garfield Tan15601662020-09-22 15:32:38 -07001151 base::Result<std::unique_ptr<InputChannel>> channel =
1152 dispatcher->createInputChannel(name);
1153 token = (*channel)->getConnectionToken();
1154 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001155 }
1156
1157 inputApplicationHandle->updateInfo();
1158 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1159
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001160 mInfo.token = token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001161 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001162 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001163 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001164 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001165 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001166 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001167 mInfo.globalScaleFactor = 1.0;
1168 mInfo.touchableRegion.clear();
1169 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001170 mInfo.ownerPid = WINDOW_PID;
1171 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001172 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001173 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001174 }
1175
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001176 sp<FakeWindowHandle> clone(int32_t displayId) {
1177 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1178 handle->mInfo = mInfo;
1179 handle->mInfo.displayId = displayId;
1180 handle->mInfo.id = sId++;
1181 handle->mInputReceiver = mInputReceiver;
1182 return handle;
1183 }
1184
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001185 void setTouchable(bool touchable) {
1186 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1187 }
chaviwd1c23182019-12-20 18:44:56 -08001188
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001189 void setFocusable(bool focusable) {
1190 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1191 }
1192
1193 void setVisible(bool visible) {
1194 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1195 }
Vishnu Nair958da932020-08-21 17:12:37 -07001196
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001197 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001198 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001199 }
1200
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001201 void setPaused(bool paused) {
1202 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1203 }
1204
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001205 void setPreventSplitting(bool preventSplitting) {
1206 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001207 }
1208
1209 void setSlippery(bool slippery) {
1210 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1211 }
1212
1213 void setWatchOutsideTouch(bool watchOutside) {
1214 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1215 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001216
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001217 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1218
1219 void setInterceptsStylus(bool interceptsStylus) {
1220 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1221 }
1222
1223 void setDropInput(bool dropInput) {
1224 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1225 }
1226
1227 void setDropInputIfObscured(bool dropInputIfObscured) {
1228 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1229 }
1230
1231 void setNoInputChannel(bool noInputChannel) {
1232 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1233 }
1234
Josep del Riob3981622023-04-18 15:49:45 +00001235 void setDisableUserActivity(bool disableUserActivity) {
1236 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1237 }
1238
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07001239 void setGlobalStylusBlocksTouch(bool shouldGlobalStylusBlockTouch) {
1240 mInfo.setInputConfig(WindowInfo::InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH,
1241 shouldGlobalStylusBlockTouch);
1242 }
1243
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001244 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1245
chaviw3277faf2021-05-19 16:45:23 -05001246 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001247
Bernardo Rufino7393d172021-02-26 13:56:11 +00001248 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1249
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001250 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001251 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001252 mInfo.touchableRegion.clear();
1253 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001254
1255 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1256 ui::Transform translate;
1257 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1258 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001259 }
1260
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001261 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1262
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001263 void setIsWallpaper(bool isWallpaper) {
1264 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1265 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001266
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001267 void setDupTouchToWallpaper(bool hasWallpaper) {
1268 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1269 }
chaviwd1c23182019-12-20 18:44:56 -08001270
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001271 void setTrustedOverlay(bool trustedOverlay) {
1272 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1273 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001274
chaviw9eaa22c2020-07-01 16:21:27 -07001275 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1276 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1277 }
1278
1279 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001280
yunho.shinf4a80b82020-11-16 21:13:57 +09001281 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1282
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001283 std::unique_ptr<KeyEvent> consumeKey(bool handled = true) {
1284 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED, handled);
1285 if (event == nullptr) {
1286 ADD_FAILURE() << "No event";
1287 return nullptr;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001288 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001289 if (event->getType() != InputEventType::KEY) {
1290 ADD_FAILURE() << "Instead of key event, got " << event;
1291 return nullptr;
1292 }
1293 return std::unique_ptr<KeyEvent>(static_cast<KeyEvent*>(event.release()));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001294 }
1295
1296 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001297 std::unique_ptr<KeyEvent> keyEvent = consumeKey();
1298 ASSERT_NE(nullptr, keyEvent);
1299 ASSERT_THAT(*keyEvent, matcher);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001300 }
1301
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001302 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001303 consumeKeyEvent(AllOf(WithKeyAction(ACTION_DOWN), WithDisplayId(expectedDisplayId),
1304 WithFlags(expectedFlags)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001305 }
1306
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001307 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001308 consumeKeyEvent(AllOf(WithKeyAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1309 WithFlags(expectedFlags)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001310 }
1311
Svet Ganov5d3bc372020-01-26 23:11:07 -08001312 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001313 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001314 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1315 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001316 }
1317
1318 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001319 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001320 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1321 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001322 }
1323
1324 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001325 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001326 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1327 }
1328
1329 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1330 std::optional<int32_t> expectedFlags = std::nullopt) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001331 consumeMotionEvent(
1332 AllOf(WithMotionAction(ACTION_DOWN),
1333 testing::Conditional(expectedDisplayId.has_value(),
1334 WithDisplayId(*expectedDisplayId), testing::_),
1335 testing::Conditional(expectedFlags.has_value(), WithFlags(*expectedFlags),
1336 testing::_)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001337 }
1338
Svet Ganov5d3bc372020-01-26 23:11:07 -08001339 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001340 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1341 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001342 const int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001343 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001344 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1345 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001346 }
1347
1348 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001349 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001350 const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001351 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001352 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1353 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001354 }
1355
1356 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001357 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001358 consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1359 WithFlags(expectedFlags)));
Michael Wright3a240c42019-12-10 20:53:41 +00001360 }
1361
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001362 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1363 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001364 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE),
1365 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001366 }
1367
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001368 void consumeMotionOutsideWithZeroedCoords() {
1369 consumeMotionEvent(
1370 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE), WithRawCoords(0, 0)));
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001371 }
1372
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001373 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1374 ASSERT_NE(mInputReceiver, nullptr)
1375 << "Cannot consume events from a window with no receiver";
1376 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1377 }
1378
Prabir Pradhan99987712020-11-10 18:43:05 -08001379 void consumeCaptureEvent(bool hasCapture) {
1380 ASSERT_NE(mInputReceiver, nullptr)
1381 << "Cannot consume events from a window with no receiver";
1382 mInputReceiver->consumeCaptureEvent(hasCapture);
1383 }
1384
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001385 std::unique_ptr<MotionEvent> consumeMotionEvent(
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001386 const ::testing::Matcher<MotionEvent>& matcher = testing::_) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001387 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
1388 if (event == nullptr) {
1389 ADD_FAILURE() << "No event";
1390 return nullptr;
Prabir Pradhan5893d362023-11-17 04:30:40 +00001391 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001392 if (event->getType() != InputEventType::MOTION) {
1393 ADD_FAILURE() << "Instead of motion event, got " << *event;
1394 return nullptr;
1395 }
1396 std::unique_ptr<MotionEvent> motionEvent =
1397 std::unique_ptr<MotionEvent>(static_cast<MotionEvent*>(event.release()));
1398 EXPECT_THAT(*motionEvent, matcher);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001399 return motionEvent;
chaviwd1c23182019-12-20 18:44:56 -08001400 }
1401
arthurhungb89ccb02020-12-30 16:19:01 +08001402 void consumeDragEvent(bool isExiting, float x, float y) {
1403 mInputReceiver->consumeDragEvent(isExiting, x, y);
1404 }
1405
Antonio Kantekf16f2832021-09-28 04:39:20 +00001406 void consumeTouchModeEvent(bool inTouchMode) {
1407 ASSERT_NE(mInputReceiver, nullptr)
1408 << "Cannot consume events from a window with no receiver";
1409 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1410 }
1411
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001412 std::pair<std::optional<uint32_t>, std::unique_ptr<InputEvent>> receiveEvent() {
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001413 return receive();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001414 }
1415
1416 void finishEvent(uint32_t sequenceNum) {
1417 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1418 mInputReceiver->finishEvent(sequenceNum);
1419 }
1420
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001421 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1422 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1423 mInputReceiver->sendTimeline(inputEventId, timeline);
1424 }
1425
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001426 void assertNoEvents(std::chrono::milliseconds timeout = CONSUME_TIMEOUT_NO_EVENT_EXPECTED) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001427 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001428 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001429 return; // Can't receive events if the window does not have input channel
1430 }
1431 ASSERT_NE(nullptr, mInputReceiver)
1432 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001433 mInputReceiver->assertNoEvents(timeout);
Arthur Hungb92218b2018-08-14 12:00:21 +08001434 }
1435
chaviwaf87b3e2019-10-01 16:59:28 -07001436 sp<IBinder> getToken() { return mInfo.token; }
1437
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001438 const std::string& getName() { return mName; }
1439
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001440 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001441 mInfo.ownerPid = ownerPid;
1442 mInfo.ownerUid = ownerUid;
1443 }
1444
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001445 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001446
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001447 void destroyReceiver() { mInputReceiver = nullptr; }
1448
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001449 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1450
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001451 // FakeWindowHandle uses this consume method to ensure received events are added to the trace.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001452 std::unique_ptr<InputEvent> consume(std::chrono::milliseconds timeout, bool handled = true) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001453 if (mInputReceiver == nullptr) {
1454 LOG(FATAL) << "Cannot consume event from a window with no input event receiver";
1455 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001456 std::unique_ptr<InputEvent> event = mInputReceiver->consume(timeout, handled);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001457 if (event == nullptr) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001458 ADD_FAILURE() << "Consume failed: no event";
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001459 }
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001460 expectReceivedEventTraced(event);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001461 return event;
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001462 }
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001463
1464private:
1465 FakeWindowHandle(std::string name) : mName(name){};
1466 const std::string mName;
1467 std::shared_ptr<FakeInputReceiver> mInputReceiver;
1468 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
1469 friend class sp<FakeWindowHandle>;
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001470
1471 // FakeWindowHandle uses this receive method to ensure received events are added to the trace.
1472 std::pair<std::optional<uint32_t /*seq*/>, std::unique_ptr<InputEvent>> receive() {
1473 if (mInputReceiver == nullptr) {
1474 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1475 return std::make_pair(std::nullopt, nullptr);
1476 }
1477 auto out = mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1478 const auto& [_, event] = out;
1479 expectReceivedEventTraced(event);
1480 return std::move(out);
1481 }
1482
1483 void expectReceivedEventTraced(const std::unique_ptr<InputEvent>& event) {
1484 if (!event) {
1485 return;
1486 }
1487
1488 switch (event->getType()) {
1489 case InputEventType::KEY: {
Prabir Pradhan4497c862023-12-15 07:13:30 +00001490 gVerifyingTrace->expectKeyDispatchTraced(static_cast<KeyEvent&>(*event), mInfo.id);
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001491 break;
1492 }
1493 case InputEventType::MOTION: {
Prabir Pradhan4497c862023-12-15 07:13:30 +00001494 gVerifyingTrace->expectMotionDispatchTraced(static_cast<MotionEvent&>(*event),
1495 mInfo.id);
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001496 break;
1497 }
1498 default:
1499 break;
1500 }
1501 }
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001502};
1503
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001504std::atomic<int32_t> FakeWindowHandle::sId{1};
1505
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001506class FakeMonitorReceiver {
1507public:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001508 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId)
1509 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001510
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001511 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001512
1513 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001514 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1515 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001516 }
1517
1518 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001519 const auto [sequenceNum, _] = mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1520 return sequenceNum;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001521 }
1522
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001523 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001524
1525 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001526 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1527 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001528 }
1529
1530 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001531 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1532 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001533 }
1534
1535 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001536 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1537 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001538 }
1539
1540 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001541 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001542 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1543 WithDisplayId(expectedDisplayId),
1544 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1545 }
1546
1547 void consumeMotionPointerDown(int32_t pointerIdx) {
1548 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1549 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001550 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1551 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001552 }
1553
1554 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001555 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001556 }
1557
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001558 std::unique_ptr<MotionEvent> consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001559
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001560 void assertNoEvents() { mInputReceiver.assertNoEvents(CONSUME_TIMEOUT_NO_EVENT_EXPECTED); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001561
1562private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001563 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001564};
1565
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001566static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001567 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001568 int32_t displayId = ADISPLAY_ID_NONE,
1569 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001570 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001571 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001572 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001573 KeyEvent event;
1574 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1575
1576 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001577 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001578 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1579 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001580
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001581 if (!allowKeyRepeat) {
1582 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1583 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001584 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001585 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001586}
1587
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001588static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1589 InputEventInjectionResult result =
1590 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1591 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1592 if (result != InputEventInjectionResult::TIMED_OUT) {
1593 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1594 }
1595}
1596
1597static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001598 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001599 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001600}
1601
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001602// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1603// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1604// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001605static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1606 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001607 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001608 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001609 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001610}
1611
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001612static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001613 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001614 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001615}
1616
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001617static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001618 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001619 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001620 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001621 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001622 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1623 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001624}
1625
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001626static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001627 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1628 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001629 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001630 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1631 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001632 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001633 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001634 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001635 MotionEventBuilder motionBuilder =
1636 MotionEventBuilder(action, source)
1637 .displayId(displayId)
1638 .eventTime(eventTime)
1639 .rawXCursorPosition(cursorPosition.x)
1640 .rawYCursorPosition(cursorPosition.y)
1641 .pointer(
1642 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1643 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1644 motionBuilder.downTime(eventTime);
1645 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001646
1647 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001648 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1649 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001650}
1651
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001652static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1653 int32_t displayId,
1654 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001655 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001656}
1657
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001658static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1659 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001660 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001661 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001662}
1663
Jackal Guof9696682018-10-05 12:23:23 +08001664static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1665 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1666 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001667 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1668 AINPUT_SOURCE_KEYBOARD, displayId, POLICY_FLAG_PASS_TO_USER, action,
1669 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001670
1671 return args;
1672}
1673
Josep del Riob3981622023-04-18 15:49:45 +00001674static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1675 int32_t displayId = ADISPLAY_ID_NONE) {
1676 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1677 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001678 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1679 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C,
1680 AMETA_META_ON, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001681
1682 return args;
1683}
1684
1685static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1686 int32_t displayId = ADISPLAY_ID_NONE) {
1687 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1688 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001689 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1690 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST,
1691 KEY_ASSISTANT, AMETA_NONE, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001692
1693 return args;
1694}
1695
Prabir Pradhan678438e2023-04-13 19:32:51 +00001696[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1697 int32_t displayId,
1698 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001699 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001700 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1701 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1702 }
1703
chaviwd1c23182019-12-20 18:44:56 -08001704 PointerProperties pointerProperties[pointerCount];
1705 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001706
chaviwd1c23182019-12-20 18:44:56 -08001707 for (size_t i = 0; i < pointerCount; i++) {
1708 pointerProperties[i].clear();
1709 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001710 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001711
chaviwd1c23182019-12-20 18:44:56 -08001712 pointerCoords[i].clear();
1713 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1714 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1715 }
Jackal Guof9696682018-10-05 12:23:23 +08001716
1717 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1718 // Define a valid motion event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001719 NotifyMotionArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, source,
1720 displayId, POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0,
1721 /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001722 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001723 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001724 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001725 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001726
1727 return args;
1728}
1729
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001730static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1731 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1732}
1733
chaviwd1c23182019-12-20 18:44:56 -08001734static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1735 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1736}
1737
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001738static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1739 const PointerCaptureRequest& request) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001740 return NotifyPointerCaptureChangedArgs(InputEvent::nextId(), systemTime(SYSTEM_TIME_MONOTONIC),
1741 request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001742}
1743
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001744} // namespace
1745
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001746/**
1747 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1748 * broken channel.
1749 */
1750TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1751 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1752 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001753 sp<FakeWindowHandle>::make(application, mDispatcher,
1754 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001755
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001756 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001757
1758 // Window closes its channel, but the window remains.
1759 window->destroyReceiver();
1760 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1761}
1762
Arthur Hungb92218b2018-08-14 12:00:21 +08001763TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001764 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001765 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1766 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001767
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001768 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001769 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001770 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001771 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001772
1773 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001774 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001775}
1776
Siarhei Vishniakouaeed0da2024-01-09 08:57:13 -08001777using InputDispatcherDeathTest = InputDispatcherTest;
1778
1779/**
1780 * When 'onWindowInfosChanged' arguments contain a duplicate entry for the same window, dispatcher
1781 * should crash.
1782 */
1783TEST_F(InputDispatcherDeathTest, DuplicateWindowInfosAbortDispatcher) {
1784 testing::GTEST_FLAG(death_test_style) = "threadsafe";
1785 ScopedSilentDeath _silentDeath;
1786
1787 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1788 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1789 "Fake Window", ADISPLAY_ID_DEFAULT);
1790 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
1791 {{*window->getInfo(), *window->getInfo()}, {}, 0, 0}),
1792 "Incorrect WindowInfosUpdate provided");
1793}
1794
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001795TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1796 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001797 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1798 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001799
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001800 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001801 // Inject a MotionEvent to an unknown display.
1802 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001803 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001804 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1805
1806 // Window should receive motion event.
1807 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1808}
1809
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001810/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001811 * Calling onWindowInfosChanged once should not cause any issues.
1812 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001813 * called twice.
1814 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001815TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001816 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001817 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1818 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001819 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001820
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001821 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001822 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001823 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001824 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001825 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001826
1827 // Window should receive motion event.
1828 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1829}
1830
1831/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001832 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001833 */
1834TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001835 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001836 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1837 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001838 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001839
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001840 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1841 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001842 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001843 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001844 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001845 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001846
1847 // Window should receive motion event.
1848 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1849}
1850
Arthur Hungb92218b2018-08-14 12:00:21 +08001851// The foreground window should receive the first touch down event.
1852TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001853 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001854 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001855 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001856 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001857 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001858
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001859 mDispatcher->onWindowInfosChanged(
1860 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001861 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001862 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001863 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001864
1865 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001866 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001867 windowSecond->assertNoEvents();
1868}
1869
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001870/**
1871 * Two windows: A top window, and a wallpaper behind the window.
1872 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1873 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001874 * 1. foregroundWindow <-- dup touch to wallpaper
1875 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001876 */
1877TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1878 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1879 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001880 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001881 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001882 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001883 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001884 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001885
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001886 mDispatcher->onWindowInfosChanged(
1887 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001888 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001889 injectMotionEvent(*mDispatcher,
1890 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1891 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
1892 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001893 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1894
1895 // Both foreground window and its wallpaper should receive the touch down
1896 foregroundWindow->consumeMotionDown();
1897 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1898
1899 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001900 injectMotionEvent(*mDispatcher,
1901 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1902 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
1903 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001904 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1905
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001906 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001907 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1908
1909 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001910 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001911 foregroundWindow->consumeMotionCancel();
1912 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1913 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1914}
1915
1916/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001917 * Two fingers down on the window, and lift off the first finger.
1918 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1919 * contains a single pointer.
1920 */
1921TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1922 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1923 sp<FakeWindowHandle> window =
1924 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1925
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001926 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001927 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001928 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1929 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1930 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001931 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001932 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1933 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1934 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1935 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001936 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001937 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1938 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1939 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1940 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001941 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1942 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1943 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1944
1945 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001946 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001947 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1948 window->consumeMotionEvent(
1949 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1950}
1951
1952/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001953 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1954 * with the following differences:
1955 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1956 * clean up the connection.
1957 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1958 * Ensure that there's no crash in the dispatcher.
1959 */
1960TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1961 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1962 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001963 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001964 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001965 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001966 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001967 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001968
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001969 mDispatcher->onWindowInfosChanged(
1970 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001971 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001972 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001973 {100, 200}))
1974 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1975
1976 // Both foreground window and its wallpaper should receive the touch down
1977 foregroundWindow->consumeMotionDown();
1978 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1979
1980 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001981 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001982 ADISPLAY_ID_DEFAULT, {110, 200}))
1983 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1984
1985 foregroundWindow->consumeMotionMove();
1986 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1987
1988 // Wallpaper closes its channel, but the window remains.
1989 wallpaperWindow->destroyReceiver();
1990 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1991
1992 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1993 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001994 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001995 foregroundWindow->consumeMotionCancel();
1996}
1997
Arthur Hungc539dbb2022-12-08 07:45:36 +00001998class ShouldSplitTouchFixture : public InputDispatcherTest,
1999 public ::testing::WithParamInterface<bool> {};
2000INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
2001 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08002002/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002003 * A single window that receives touch (on top), and a wallpaper window underneath it.
2004 * The top window gets a multitouch gesture.
2005 * Ensure that wallpaper gets the same gesture.
2006 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00002007TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002008 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002009 sp<FakeWindowHandle> foregroundWindow =
2010 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
2011 foregroundWindow->setDupTouchToWallpaper(true);
2012 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002013
2014 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002015 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002016 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002017
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002018 mDispatcher->onWindowInfosChanged(
2019 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002020
2021 // Touch down on top window
2022 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002023 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002024 {100, 100}))
2025 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2026
2027 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00002028 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002029 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2030
2031 // Second finger down on the top window
2032 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002033 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002034 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002035 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2036 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002037 .build();
2038 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002039 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002040 InputEventInjectionSync::WAIT_FOR_RESULT))
2041 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2042
Harry Cutts33476232023-01-30 19:57:29 +00002043 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
2044 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002045 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00002046
2047 const MotionEvent secondFingerUpEvent =
2048 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2049 .displayId(ADISPLAY_ID_DEFAULT)
2050 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002051 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2052 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002053 .build();
2054 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002055 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002056 InputEventInjectionSync::WAIT_FOR_RESULT))
2057 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2058 foregroundWindow->consumeMotionPointerUp(0);
2059 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2060
2061 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002062 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002063 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2064 AINPUT_SOURCE_TOUCHSCREEN)
2065 .displayId(ADISPLAY_ID_DEFAULT)
2066 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00002067 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002068 .x(100)
2069 .y(100))
2070 .build(),
2071 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002072 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2073 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2074 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002075}
2076
2077/**
2078 * Two windows: a window on the left and window on the right.
2079 * A third window, wallpaper, is behind both windows, and spans both top windows.
2080 * The first touch down goes to the left window. A second pointer touches down on the right window.
2081 * The touch is split, so both left and right windows should receive ACTION_DOWN.
2082 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
2083 * ACTION_POINTER_DOWN(1).
2084 */
2085TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
2086 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2087 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002088 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002089 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002090 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002091
2092 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002093 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002094 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002095 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002096
2097 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002098 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002099 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002100 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002101
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002102 mDispatcher->onWindowInfosChanged(
2103 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2104 {},
2105 0,
2106 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002107
2108 // Touch down on left window
2109 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002110 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002111 {100, 100}))
2112 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2113
2114 // Both foreground window and its wallpaper should receive the touch down
2115 leftWindow->consumeMotionDown();
2116 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2117
2118 // Second finger down on the right window
2119 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002120 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002121 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002122 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2123 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002124 .build();
2125 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002126 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002127 InputEventInjectionSync::WAIT_FOR_RESULT))
2128 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2129
2130 leftWindow->consumeMotionMove();
2131 // Since the touch is split, right window gets ACTION_DOWN
2132 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002133 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002134 expectedWallpaperFlags);
2135
2136 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002137 mDispatcher->onWindowInfosChanged(
2138 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002139 leftWindow->consumeMotionCancel();
2140 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2141 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2142
2143 // The pointer that's still down on the right window moves, and goes to the right window only.
2144 // As far as the dispatcher's concerned though, both pointers are still present.
2145 const MotionEvent secondFingerMoveEvent =
2146 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2147 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002148 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2149 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002150 .build();
2151 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002152 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002153 InputEventInjectionSync::WAIT_FOR_RESULT));
2154 rightWindow->consumeMotionMove();
2155
2156 leftWindow->assertNoEvents();
2157 rightWindow->assertNoEvents();
2158 wallpaperWindow->assertNoEvents();
2159}
2160
Arthur Hungc539dbb2022-12-08 07:45:36 +00002161/**
2162 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2163 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2164 * The right window should receive ACTION_DOWN.
2165 */
2166TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002167 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002168 sp<FakeWindowHandle> leftWindow =
2169 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2170 leftWindow->setFrame(Rect(0, 0, 200, 200));
2171 leftWindow->setDupTouchToWallpaper(true);
2172 leftWindow->setSlippery(true);
2173
2174 sp<FakeWindowHandle> rightWindow =
2175 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2176 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002177
2178 sp<FakeWindowHandle> wallpaperWindow =
2179 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2180 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002181
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002182 mDispatcher->onWindowInfosChanged(
2183 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2184 {},
2185 0,
2186 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002187
Arthur Hungc539dbb2022-12-08 07:45:36 +00002188 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002189 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002190 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002191 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002192 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002193
2194 // Both foreground window and its wallpaper should receive the touch down
2195 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002196 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2197
Arthur Hungc539dbb2022-12-08 07:45:36 +00002198 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002199 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002200 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002201 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002202 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2203
Arthur Hungc539dbb2022-12-08 07:45:36 +00002204 leftWindow->consumeMotionCancel();
2205 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2206 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002207}
2208
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002209/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002210 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2211 * interactive, it might stop sending this flag.
2212 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2213 * to have a consistent input stream.
2214 *
2215 * Test procedure:
2216 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2217 * DOWN (new gesture).
2218 *
2219 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2220 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2221 *
2222 * We technically just need a single window here, but we are using two windows (spy on top and a
2223 * regular window below) to emulate the actual situation where it happens on the device.
2224 */
2225TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2226 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2227 sp<FakeWindowHandle> spyWindow =
2228 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2229 spyWindow->setFrame(Rect(0, 0, 200, 200));
2230 spyWindow->setTrustedOverlay(true);
2231 spyWindow->setSpy(true);
2232
2233 sp<FakeWindowHandle> window =
2234 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2235 window->setFrame(Rect(0, 0, 200, 200));
2236
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002237 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002238 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002239
2240 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002241 mDispatcher->notifyMotion(
2242 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2243 .deviceId(touchDeviceId)
2244 .policyFlags(DEFAULT_POLICY_FLAGS)
2245 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2246 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002247
Prabir Pradhan678438e2023-04-13 19:32:51 +00002248 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2249 .deviceId(touchDeviceId)
2250 .policyFlags(DEFAULT_POLICY_FLAGS)
2251 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2252 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2253 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002254 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2255 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2256 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2257 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2258
2259 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002260 mDispatcher->notifyMotion(
2261 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2262 .deviceId(touchDeviceId)
2263 .policyFlags(0)
2264 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2265 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2266 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002267 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2268 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2269
2270 // We don't need to reset the device to reproduce the issue, but the reset event typically
2271 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002272 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002273
2274 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002275 mDispatcher->notifyMotion(
2276 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2277 .deviceId(touchDeviceId)
2278 .policyFlags(DEFAULT_POLICY_FLAGS)
2279 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2280 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002281 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2282 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2283
2284 // No more events
2285 spyWindow->assertNoEvents();
2286 window->assertNoEvents();
2287}
2288
2289/**
Linnan Li907ae732023-09-05 17:14:21 +08002290 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
2291 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2292 * interactive, it might stop sending this flag.
2293 * We've already ensured the consistency of the touch event in this case, and we should also ensure
2294 * the consistency of the hover event in this case.
2295 *
2296 * Test procedure:
2297 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
2298 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
2299 *
2300 * We expect to receive two full streams of hover events.
2301 */
2302TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
2303 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2304
2305 sp<FakeWindowHandle> window =
2306 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2307 window->setFrame(Rect(0, 0, 300, 300));
2308
2309 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2310
2311 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2312 .policyFlags(DEFAULT_POLICY_FLAGS)
2313 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2314 .build());
2315 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2316
2317 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2318 .policyFlags(DEFAULT_POLICY_FLAGS)
2319 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2320 .build());
2321 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2322
2323 // Send hover exit without the default policy flags.
2324 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2325 .policyFlags(0)
2326 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2327 .build());
2328
2329 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2330
2331 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
2332 // right event.
2333 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2334 .policyFlags(DEFAULT_POLICY_FLAGS)
2335 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
2336 .build());
2337 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2338
2339 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2340 .policyFlags(DEFAULT_POLICY_FLAGS)
2341 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2342 .build());
2343 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2344
2345 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2346 .policyFlags(DEFAULT_POLICY_FLAGS)
2347 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2348 .build());
2349 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2350}
2351
2352/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002353 * Two windows: a window on the left and a window on the right.
2354 * Mouse is hovered from the right window into the left window.
2355 * Next, we tap on the left window, where the cursor was last seen.
2356 * The second tap is done onto the right window.
2357 * The mouse and tap are from two different devices.
2358 * We technically don't need to set the downtime / eventtime for these events, but setting these
2359 * explicitly helps during debugging.
2360 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2361 * In the buggy implementation, a tap on the right window would cause a crash.
2362 */
2363TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2364 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2365 sp<FakeWindowHandle> leftWindow =
2366 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2367 leftWindow->setFrame(Rect(0, 0, 200, 200));
2368
2369 sp<FakeWindowHandle> rightWindow =
2370 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2371 rightWindow->setFrame(Rect(200, 0, 400, 200));
2372
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002373 mDispatcher->onWindowInfosChanged(
2374 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002375 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2376 // stale.
2377 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2378 const int32_t mouseDeviceId = 6;
2379 const int32_t touchDeviceId = 4;
2380 // Move the cursor from right
2381 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002382 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002383 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2384 AINPUT_SOURCE_MOUSE)
2385 .deviceId(mouseDeviceId)
2386 .downTime(baseTime + 10)
2387 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002388 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002389 .build()));
2390 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2391
2392 // .. to the left window
2393 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002394 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002395 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2396 AINPUT_SOURCE_MOUSE)
2397 .deviceId(mouseDeviceId)
2398 .downTime(baseTime + 10)
2399 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002400 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002401 .build()));
2402 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2403 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2404 // Now tap the left window
2405 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002406 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002407 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2408 AINPUT_SOURCE_TOUCHSCREEN)
2409 .deviceId(touchDeviceId)
2410 .downTime(baseTime + 40)
2411 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002412 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002413 .build()));
2414 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2415 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2416
2417 // release tap
2418 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002419 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002420 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2421 AINPUT_SOURCE_TOUCHSCREEN)
2422 .deviceId(touchDeviceId)
2423 .downTime(baseTime + 40)
2424 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002425 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002426 .build()));
2427 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2428
2429 // Tap the window on the right
2430 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002431 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002432 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2433 AINPUT_SOURCE_TOUCHSCREEN)
2434 .deviceId(touchDeviceId)
2435 .downTime(baseTime + 60)
2436 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002437 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002438 .build()));
2439 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2440
2441 // release tap
2442 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002443 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002444 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2445 AINPUT_SOURCE_TOUCHSCREEN)
2446 .deviceId(touchDeviceId)
2447 .downTime(baseTime + 60)
2448 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002449 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002450 .build()));
2451 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2452
2453 // No more events
2454 leftWindow->assertNoEvents();
2455 rightWindow->assertNoEvents();
2456}
2457
2458/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002459 * Start hovering in a window. While this hover is still active, make another window appear on top.
2460 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2461 * While the top window is present, the hovering is stopped.
2462 * Later, hovering gets resumed again.
2463 * Ensure that new hover gesture is handled correctly.
2464 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2465 * to the window that's currently being hovered over.
2466 */
2467TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2468 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2469 sp<FakeWindowHandle> window =
2470 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2471 window->setFrame(Rect(0, 0, 200, 200));
2472
2473 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002474 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002475
2476 // Start hovering in the window
2477 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2478 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2479 .build());
2480 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2481
2482 // Now, an obscuring window appears!
2483 sp<FakeWindowHandle> obscuringWindow =
2484 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2485 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002486 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002487 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2488 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2489 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2490 obscuringWindow->setNoInputChannel(true);
2491 obscuringWindow->setFocusable(false);
2492 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002493 mDispatcher->onWindowInfosChanged(
2494 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002495
2496 // While this new obscuring window is present, the hovering is stopped
2497 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2498 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2499 .build());
2500 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2501
2502 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002503 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002504
2505 // And a new hover gesture starts.
2506 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2507 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2508 .build());
2509 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2510}
2511
2512/**
2513 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2514 * the obscuring window.
2515 */
2516TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2517 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2518 sp<FakeWindowHandle> window =
2519 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2520 window->setFrame(Rect(0, 0, 200, 200));
2521
2522 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002523 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002524
2525 // Start hovering in the window
2526 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2527 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2528 .build());
2529 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2530
2531 // Now, an obscuring window appears!
2532 sp<FakeWindowHandle> obscuringWindow =
2533 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2534 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002535 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002536 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2537 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2538 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2539 obscuringWindow->setNoInputChannel(true);
2540 obscuringWindow->setFocusable(false);
2541 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002542 mDispatcher->onWindowInfosChanged(
2543 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002544
2545 // While this new obscuring window is present, the hovering continues. The event can't go to the
2546 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2547 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2548 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2549 .build());
2550 obscuringWindow->assertNoEvents();
2551 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2552
2553 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002554 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002555
2556 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2557 // so it should generate a HOVER_ENTER
2558 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2559 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2560 .build());
2561 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2562
2563 // Now the MOVE should be getting dispatched normally
2564 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2565 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2566 .build());
2567 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2568}
2569
2570/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002571 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2572 * events are delivered to the window.
2573 */
2574TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2575 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2576 sp<FakeWindowHandle> window =
2577 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2578 window->setFrame(Rect(0, 0, 200, 200));
2579 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2580
2581 // Start hovering in the window
2582 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2583 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2584 .build());
2585 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2586
2587 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2588 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2589 .build());
2590 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2591
2592 // Scroll with the mouse
2593 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2594 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2595 .build());
2596 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2597}
2598
2599using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2600
2601/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002602 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2603 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002604 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002605TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002606 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2607 sp<FakeWindowHandle> window =
2608 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2609 window->setFrame(Rect(0, 0, 200, 200));
2610
2611 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2612
2613 constexpr int32_t touchDeviceId = 4;
2614 constexpr int32_t stylusDeviceId = 2;
2615
2616 // Stylus down
2617 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2618 .deviceId(stylusDeviceId)
2619 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2620 .build());
2621 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2622
2623 // Touch down
2624 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2625 .deviceId(touchDeviceId)
2626 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2627 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002628
2629 // Touch move
2630 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2631 .deviceId(touchDeviceId)
2632 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2633 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002634 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002635
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002636 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002637 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2638 .deviceId(stylusDeviceId)
2639 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2640 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002641 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2642 WithCoords(101, 111)));
2643
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002644 window->assertNoEvents();
2645}
2646
2647/**
2648 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002649 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002650 * Similar test as above, but with added SPY window.
2651 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002652TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002653 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2654 sp<FakeWindowHandle> window =
2655 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2656 sp<FakeWindowHandle> spyWindow =
2657 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2658 spyWindow->setFrame(Rect(0, 0, 200, 200));
2659 spyWindow->setTrustedOverlay(true);
2660 spyWindow->setSpy(true);
2661 window->setFrame(Rect(0, 0, 200, 200));
2662
2663 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2664
2665 constexpr int32_t touchDeviceId = 4;
2666 constexpr int32_t stylusDeviceId = 2;
2667
2668 // Stylus down
2669 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2670 .deviceId(stylusDeviceId)
2671 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2672 .build());
2673 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2674 spyWindow->consumeMotionEvent(
2675 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2676
2677 // Touch down
2678 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2679 .deviceId(touchDeviceId)
2680 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2681 .build());
2682
2683 // Touch move
2684 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2685 .deviceId(touchDeviceId)
2686 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2687 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002688
2689 // Touch is ignored because stylus is already down
2690
2691 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002692 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2693 .deviceId(stylusDeviceId)
2694 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2695 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002696 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2697 WithCoords(101, 111)));
2698 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2699 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002700
2701 window->assertNoEvents();
2702 spyWindow->assertNoEvents();
2703}
2704
2705/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002706 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002707 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002708 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002709TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002710 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2711 sp<FakeWindowHandle> window =
2712 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2713 window->setFrame(Rect(0, 0, 200, 200));
2714
2715 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2716
2717 constexpr int32_t touchDeviceId = 4;
2718 constexpr int32_t stylusDeviceId = 2;
2719
2720 // Stylus down on the window
2721 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2722 .deviceId(stylusDeviceId)
2723 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2724 .build());
2725 window->consumeMotionEvent(
2726 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2727
2728 // Touch down on window
2729 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2730 .deviceId(touchDeviceId)
2731 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2732 .build());
2733 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2734 .deviceId(touchDeviceId)
2735 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2736 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002737
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002738 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002739
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002740 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002741 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2742 .deviceId(stylusDeviceId)
2743 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2744 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002745 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2746 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002747
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002748 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002749 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2750 .deviceId(touchDeviceId)
2751 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2752 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002753 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002754}
2755
2756/**
2757 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002758 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002759 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002760TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002761 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2762 sp<FakeWindowHandle> window =
2763 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2764 window->setFrame(Rect(0, 0, 200, 200));
2765
2766 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2767
2768 constexpr int32_t touchDeviceId = 4;
2769 constexpr int32_t stylusDeviceId = 2;
2770
2771 // Touch down on window
2772 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2773 .deviceId(touchDeviceId)
2774 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2775 .build());
2776 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2777 .deviceId(touchDeviceId)
2778 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2779 .build());
2780 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2781 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2782
2783 // Stylus hover on the window
2784 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2785 .deviceId(stylusDeviceId)
2786 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2787 .build());
2788 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2789 .deviceId(stylusDeviceId)
2790 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2791 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002792 // Stylus hover movement causes touch to be canceled
2793 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2794 WithCoords(141, 146)));
2795 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2796 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2797 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2798 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002799
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002800 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002801 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2802 .deviceId(touchDeviceId)
2803 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2804 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002805
2806 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002807}
2808
2809/**
2810 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2811 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2812 * become active.
2813 */
2814TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
2815 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2816 sp<FakeWindowHandle> window =
2817 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2818 window->setFrame(Rect(0, 0, 200, 200));
2819
2820 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2821
2822 constexpr int32_t stylusDeviceId1 = 3;
2823 constexpr int32_t stylusDeviceId2 = 5;
2824
2825 // Touch down on window
2826 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2827 .deviceId(stylusDeviceId1)
2828 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2829 .build());
2830 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2831 .deviceId(stylusDeviceId1)
2832 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2833 .build());
2834 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2835 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2836
2837 // Second stylus down
2838 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2839 .deviceId(stylusDeviceId2)
2840 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2841 .build());
2842 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2843 .deviceId(stylusDeviceId2)
2844 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2845 .build());
2846
2847 // First stylus is canceled, second one takes over.
2848 window->consumeMotionEvent(
2849 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2850 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2851 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2852
2853 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2854 .deviceId(stylusDeviceId1)
2855 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2856 .build());
2857 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002858 window->assertNoEvents();
2859}
2860
2861/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002862 * One window. Touch down on the window. Then, stylus down on the window from another device.
2863 * Ensure that is canceled, because stylus down should be preferred over touch.
2864 */
2865TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
2866 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2867 sp<FakeWindowHandle> window =
2868 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2869 window->setFrame(Rect(0, 0, 200, 200));
2870
2871 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2872
2873 constexpr int32_t touchDeviceId = 4;
2874 constexpr int32_t stylusDeviceId = 2;
2875
2876 // Touch down on window
2877 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2878 .deviceId(touchDeviceId)
2879 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2880 .build());
2881 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2882 .deviceId(touchDeviceId)
2883 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2884 .build());
2885 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2886 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2887
2888 // Stylus down on the window
2889 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2890 .deviceId(stylusDeviceId)
2891 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2892 .build());
2893 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2894 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2895
2896 // Subsequent stylus movements are delivered correctly
2897 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2898 .deviceId(stylusDeviceId)
2899 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2900 .build());
2901 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2902 WithCoords(101, 111)));
2903}
2904
2905/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002906 * Two windows: a window on the left and a window on the right.
2907 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2908 * down. Then, on the left window, also place second touch pointer down.
2909 * This test tries to reproduce a crash.
2910 * In the buggy implementation, second pointer down on the left window would cause a crash.
2911 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002912TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002913 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2914 sp<FakeWindowHandle> leftWindow =
2915 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2916 leftWindow->setFrame(Rect(0, 0, 200, 200));
2917
2918 sp<FakeWindowHandle> rightWindow =
2919 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2920 rightWindow->setFrame(Rect(200, 0, 400, 200));
2921
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002922 mDispatcher->onWindowInfosChanged(
2923 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002924
2925 const int32_t touchDeviceId = 4;
2926 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002927
2928 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002929 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2930 .deviceId(mouseDeviceId)
2931 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2932 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002933 leftWindow->consumeMotionEvent(
2934 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2935
2936 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002937 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2938 .deviceId(mouseDeviceId)
2939 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2940 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2941 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002942
2943 leftWindow->consumeMotionEvent(
2944 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2945 leftWindow->consumeMotionEvent(
2946 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2947
Prabir Pradhan678438e2023-04-13 19:32:51 +00002948 mDispatcher->notifyMotion(
2949 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2950 .deviceId(mouseDeviceId)
2951 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2952 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2953 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2954 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002955 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2956
2957 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002958 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2959 .deviceId(touchDeviceId)
2960 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2961 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002962 leftWindow->assertNoEvents();
2963
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002964 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2965
2966 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002967 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2968 .deviceId(touchDeviceId)
2969 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2970 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2971 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002972 // Since this is now a new splittable pointer going down on the left window, and it's coming
2973 // from a different device, the current gesture in the left window (pointer down) should first
2974 // be canceled.
2975 leftWindow->consumeMotionEvent(
2976 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002977 leftWindow->consumeMotionEvent(
2978 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2979 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2980 // current implementation.
2981 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2982 rightWindow->consumeMotionEvent(
2983 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2984
2985 leftWindow->assertNoEvents();
2986 rightWindow->assertNoEvents();
2987}
2988
2989/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002990 * Two windows: a window on the left and a window on the right.
2991 * Mouse is hovered on the left window and stylus is hovered on the right window.
2992 */
2993TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2994 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2995 sp<FakeWindowHandle> leftWindow =
2996 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2997 leftWindow->setFrame(Rect(0, 0, 200, 200));
2998
2999 sp<FakeWindowHandle> rightWindow =
3000 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3001 rightWindow->setFrame(Rect(200, 0, 400, 200));
3002
3003 mDispatcher->onWindowInfosChanged(
3004 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3005
3006 const int32_t stylusDeviceId = 3;
3007 const int32_t mouseDeviceId = 6;
3008
3009 // Start hovering over the left window
3010 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3011 .deviceId(mouseDeviceId)
3012 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
3013 .build());
3014 leftWindow->consumeMotionEvent(
3015 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3016
3017 // Stylus hovered on right window
3018 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3019 .deviceId(stylusDeviceId)
3020 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
3021 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003022 rightWindow->consumeMotionEvent(
3023 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3024
3025 // Subsequent HOVER_MOVE events are dispatched correctly.
3026 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
3027 .deviceId(mouseDeviceId)
3028 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
3029 .build());
3030 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003031 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003032
3033 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3034 .deviceId(stylusDeviceId)
3035 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
3036 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003037 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003038 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003039
3040 leftWindow->assertNoEvents();
3041 rightWindow->assertNoEvents();
3042}
3043
3044/**
3045 * Three windows: a window on the left and a window on the right.
3046 * And a spy window that's positioned above all of them.
3047 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
3048 * Check the stream that's received by the spy.
3049 */
3050TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
3051 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3052
3053 sp<FakeWindowHandle> spyWindow =
3054 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3055 spyWindow->setFrame(Rect(0, 0, 400, 400));
3056 spyWindow->setTrustedOverlay(true);
3057 spyWindow->setSpy(true);
3058
3059 sp<FakeWindowHandle> leftWindow =
3060 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3061 leftWindow->setFrame(Rect(0, 0, 200, 200));
3062
3063 sp<FakeWindowHandle> rightWindow =
3064 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3065
3066 rightWindow->setFrame(Rect(200, 0, 400, 200));
3067
3068 mDispatcher->onWindowInfosChanged(
3069 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3070
3071 const int32_t stylusDeviceId = 1;
3072 const int32_t touchDeviceId = 2;
3073
3074 // Stylus down on the left window
3075 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3076 .deviceId(stylusDeviceId)
3077 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3078 .build());
3079 leftWindow->consumeMotionEvent(
3080 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3081 spyWindow->consumeMotionEvent(
3082 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3083
3084 // Touch down on the right window
3085 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3086 .deviceId(touchDeviceId)
3087 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3088 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003089 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003090 rightWindow->consumeMotionEvent(
3091 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003092
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003093 // Spy window does not receive touch events, because stylus events take precedence, and it
3094 // already has an active stylus gesture.
3095
3096 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003097 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3098 .deviceId(stylusDeviceId)
3099 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3100 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003101 leftWindow->consumeMotionEvent(
3102 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3103 spyWindow->consumeMotionEvent(
3104 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003105
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003106 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003107 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3108 .deviceId(touchDeviceId)
3109 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
3110 .build());
3111 rightWindow->consumeMotionEvent(
3112 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003113
3114 spyWindow->assertNoEvents();
3115 leftWindow->assertNoEvents();
3116 rightWindow->assertNoEvents();
3117}
3118
3119/**
3120 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3121 * both.
3122 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003123 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003124 * At the same time, left and right should be getting independent streams of hovering and touch,
3125 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003126 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003127TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003128 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3129
3130 sp<FakeWindowHandle> spyWindow =
3131 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3132 spyWindow->setFrame(Rect(0, 0, 400, 400));
3133 spyWindow->setTrustedOverlay(true);
3134 spyWindow->setSpy(true);
3135
3136 sp<FakeWindowHandle> leftWindow =
3137 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3138 leftWindow->setFrame(Rect(0, 0, 200, 200));
3139
3140 sp<FakeWindowHandle> rightWindow =
3141 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3142 rightWindow->setFrame(Rect(200, 0, 400, 200));
3143
3144 mDispatcher->onWindowInfosChanged(
3145 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3146
3147 const int32_t stylusDeviceId = 1;
3148 const int32_t touchDeviceId = 2;
3149
3150 // Stylus hover on the left window
3151 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3152 .deviceId(stylusDeviceId)
3153 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3154 .build());
3155 leftWindow->consumeMotionEvent(
3156 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3157 spyWindow->consumeMotionEvent(
3158 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3159
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003160 // Touch down on the right window. Spy doesn't receive this touch because it already has
3161 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003162 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3163 .deviceId(touchDeviceId)
3164 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3165 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003166 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003167 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003168 rightWindow->consumeMotionEvent(
3169 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3170
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003171 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003172 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3173 .deviceId(stylusDeviceId)
3174 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3175 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003176 leftWindow->consumeMotionEvent(
3177 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003178 spyWindow->consumeMotionEvent(
3179 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003180
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003181 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003182 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3183 .deviceId(touchDeviceId)
3184 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3185 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003186 rightWindow->consumeMotionEvent(
3187 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3188
3189 spyWindow->assertNoEvents();
3190 leftWindow->assertNoEvents();
3191 rightWindow->assertNoEvents();
3192}
3193
3194/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003195 * On a single window, use two different devices: mouse and touch.
3196 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3197 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3198 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3199 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3200 * represent a new gesture.
3201 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003202TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003203 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3204 sp<FakeWindowHandle> window =
3205 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3206 window->setFrame(Rect(0, 0, 400, 400));
3207
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003208 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003209
3210 const int32_t touchDeviceId = 4;
3211 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003212
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003213 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003214 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3215 .deviceId(touchDeviceId)
3216 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3217 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003218 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003219 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3220 .deviceId(touchDeviceId)
3221 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3222 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3223 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003224 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003225 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3226 .deviceId(touchDeviceId)
3227 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3228 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3229 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003230 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3231 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3232 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3233
3234 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003235 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3236 .deviceId(mouseDeviceId)
3237 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3238 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3239 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003240
3241 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003242 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003243 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3244
Prabir Pradhan678438e2023-04-13 19:32:51 +00003245 mDispatcher->notifyMotion(
3246 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3247 .deviceId(mouseDeviceId)
3248 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3249 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3250 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3251 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003252 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3253
3254 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003255 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3256 .deviceId(touchDeviceId)
3257 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3258 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3259 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003260 // Since we already canceled this touch gesture, it will be ignored until a completely new
3261 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3262 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3263 // However, mouse movements should continue to work.
3264 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3265 .deviceId(mouseDeviceId)
3266 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3267 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3268 .build());
3269 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3270
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003271 window->assertNoEvents();
3272}
3273
3274/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003275 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3276 * the injected event.
3277 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003278TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003279 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3280 sp<FakeWindowHandle> window =
3281 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3282 window->setFrame(Rect(0, 0, 400, 400));
3283
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003284 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003285
3286 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003287 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3288 // completion.
3289 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003290 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003291 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3292 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003293 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003294 .build()));
3295 window->consumeMotionEvent(
3296 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3297
3298 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3299 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003300 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3301 .deviceId(touchDeviceId)
3302 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3303 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003304
3305 window->consumeMotionEvent(
3306 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3307 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3308}
3309
3310/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003311 * This test is similar to the test above, but the sequence of injected events is different.
3312 *
3313 * Two windows: a window on the left and a window on the right.
3314 * Mouse is hovered over the left window.
3315 * Next, we tap on the left window, where the cursor was last seen.
3316 *
3317 * After that, we inject one finger down onto the right window, and then a second finger down onto
3318 * the left window.
3319 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3320 * window (first), and then another on the left window (second).
3321 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3322 * In the buggy implementation, second finger down on the left window would cause a crash.
3323 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003324TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003325 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3326 sp<FakeWindowHandle> leftWindow =
3327 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3328 leftWindow->setFrame(Rect(0, 0, 200, 200));
3329
3330 sp<FakeWindowHandle> rightWindow =
3331 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3332 rightWindow->setFrame(Rect(200, 0, 400, 200));
3333
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003334 mDispatcher->onWindowInfosChanged(
3335 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003336
3337 const int32_t mouseDeviceId = 6;
3338 const int32_t touchDeviceId = 4;
3339 // Hover over the left window. Keep the cursor there.
3340 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003341 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003342 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3343 AINPUT_SOURCE_MOUSE)
3344 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003345 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003346 .build()));
3347 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3348
3349 // Tap on left window
3350 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003351 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003352 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3353 AINPUT_SOURCE_TOUCHSCREEN)
3354 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003355 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003356 .build()));
3357
3358 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003359 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003360 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3361 AINPUT_SOURCE_TOUCHSCREEN)
3362 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003363 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003364 .build()));
3365 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3366 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3367 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3368
3369 // First finger down on right window
3370 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003371 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003372 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3373 AINPUT_SOURCE_TOUCHSCREEN)
3374 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003375 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003376 .build()));
3377 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3378
3379 // Second finger down on the left window
3380 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003381 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003382 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3383 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003384 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3385 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003386 .build()));
3387 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3388 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3389
3390 // No more events
3391 leftWindow->assertNoEvents();
3392 rightWindow->assertNoEvents();
3393}
3394
3395/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003396 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3397 * While the touch is down, new hover events from the stylus device should be ignored. After the
3398 * touch is gone, stylus hovering should start working again.
3399 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003400TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003401 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3402 sp<FakeWindowHandle> window =
3403 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3404 window->setFrame(Rect(0, 0, 200, 200));
3405
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003406 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003407
3408 const int32_t stylusDeviceId = 5;
3409 const int32_t touchDeviceId = 4;
3410 // Start hovering with stylus
3411 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003412 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003413 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003414 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003415 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003416 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003417 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003418
3419 // Finger down on the window
3420 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003421 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003422 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003423 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003424 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003425 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003426 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003427
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003428 // Continue hovering with stylus.
3429 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003430 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003431 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3432 AINPUT_SOURCE_STYLUS)
3433 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003434 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003435 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003436 // Hovers continue to work
3437 window->consumeMotionEvent(
3438 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003439
3440 // Lift up the finger
3441 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003442 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003443 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3444 AINPUT_SOURCE_TOUCHSCREEN)
3445 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003446 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003447 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003448
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003449 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003450 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003451 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3452 AINPUT_SOURCE_STYLUS)
3453 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003454 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003455 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003456 window->consumeMotionEvent(
3457 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003458 window->assertNoEvents();
3459}
3460
3461/**
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003462 * If stylus is down anywhere on the screen, then touches should not be delivered to windows that
3463 * have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3464 *
3465 * Two windows: one on the left and one on the right.
3466 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3467 * Stylus down on the left window, and then touch down on the right window.
3468 * Check that the right window doesn't get touches while the stylus is down on the left window.
3469 */
3470TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusDownBlocksTouch) {
3471 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3472 sp<FakeWindowHandle> leftWindow =
3473 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3474 ADISPLAY_ID_DEFAULT);
3475 leftWindow->setFrame(Rect(0, 0, 100, 100));
3476
3477 sp<FakeWindowHandle> sbtRightWindow =
3478 sp<FakeWindowHandle>::make(application, mDispatcher,
3479 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3480 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3481 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3482
3483 mDispatcher->onWindowInfosChanged(
3484 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3485
3486 const int32_t stylusDeviceId = 5;
3487 const int32_t touchDeviceId = 4;
3488
3489 // Stylus down in the left window
3490 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3491 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3492 .deviceId(stylusDeviceId)
3493 .build());
3494 leftWindow->consumeMotionEvent(
3495 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3496
3497 // Finger tap on the right window
3498 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3499 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3500 .deviceId(touchDeviceId)
3501 .build());
3502 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3503 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3504 .deviceId(touchDeviceId)
3505 .build());
3506
3507 // The touch should be blocked, because stylus is down somewhere else on screen!
3508 sbtRightWindow->assertNoEvents();
3509
3510 // Continue stylus motion, and ensure it's not impacted.
3511 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3512 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3513 .deviceId(stylusDeviceId)
3514 .build());
3515 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3516 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3517 .deviceId(stylusDeviceId)
3518 .build());
3519 leftWindow->consumeMotionEvent(
3520 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3521 leftWindow->consumeMotionEvent(
3522 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(stylusDeviceId)));
3523
3524 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3525 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3526 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3527 .deviceId(touchDeviceId)
3528 .build());
3529 sbtRightWindow->consumeMotionEvent(
3530 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3531}
3532
3533/**
3534 * If stylus is hovering anywhere on the screen, then touches should not be delivered to windows
3535 * that have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3536 *
3537 * Two windows: one on the left and one on the right.
3538 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3539 * Stylus hover on the left window, and then touch down on the right window.
3540 * Check that the right window doesn't get touches while the stylus is hovering on the left window.
3541 */
3542TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusHoverBlocksTouch) {
3543 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3544 sp<FakeWindowHandle> leftWindow =
3545 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3546 ADISPLAY_ID_DEFAULT);
3547 leftWindow->setFrame(Rect(0, 0, 100, 100));
3548
3549 sp<FakeWindowHandle> sbtRightWindow =
3550 sp<FakeWindowHandle>::make(application, mDispatcher,
3551 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3552 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3553 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3554
3555 mDispatcher->onWindowInfosChanged(
3556 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3557
3558 const int32_t stylusDeviceId = 5;
3559 const int32_t touchDeviceId = 4;
3560
3561 // Stylus hover in the left window
3562 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3563 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3564 .deviceId(stylusDeviceId)
3565 .build());
3566 leftWindow->consumeMotionEvent(
3567 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3568
3569 // Finger tap on the right window
3570 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3571 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3572 .deviceId(touchDeviceId)
3573 .build());
3574 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3575 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3576 .deviceId(touchDeviceId)
3577 .build());
3578
3579 // The touch should be blocked, because stylus is hovering somewhere else on screen!
3580 sbtRightWindow->assertNoEvents();
3581
3582 // Continue stylus motion, and ensure it's not impacted.
3583 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3584 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3585 .deviceId(stylusDeviceId)
3586 .build());
3587 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3588 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3589 .deviceId(stylusDeviceId)
3590 .build());
3591 leftWindow->consumeMotionEvent(
3592 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3593 leftWindow->consumeMotionEvent(
3594 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3595
3596 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3597 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3598 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3599 .deviceId(touchDeviceId)
3600 .build());
3601 sbtRightWindow->consumeMotionEvent(
3602 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3603}
3604
3605/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003606 * A spy window above a window with no input channel.
3607 * Start hovering with a stylus device, and then tap with it.
3608 * Ensure spy window receives the entire sequence.
3609 */
3610TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3611 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3612 sp<FakeWindowHandle> spyWindow =
3613 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3614 spyWindow->setFrame(Rect(0, 0, 200, 200));
3615 spyWindow->setTrustedOverlay(true);
3616 spyWindow->setSpy(true);
3617 sp<FakeWindowHandle> window =
3618 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3619 window->setNoInputChannel(true);
3620 window->setFrame(Rect(0, 0, 200, 200));
3621
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003622 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003623
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003624 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003625 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3626 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3627 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003628 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3629 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003630 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3631 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3632 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003633 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3634
3635 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003636 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3637 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3638 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003639 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3640
3641 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003642 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3643 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3644 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003645 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3646
3647 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003648 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3649 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3650 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003651 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3652 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003653 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3654 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3655 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003656 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3657
3658 // No more events
3659 spyWindow->assertNoEvents();
3660 window->assertNoEvents();
3661}
3662
3663/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003664 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3665 * rejected. But since we already have an ongoing gesture, this event should be processed.
3666 * This prevents inconsistent events being handled inside the dispatcher.
3667 */
3668TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3669 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3670
3671 sp<FakeWindowHandle> window =
3672 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3673 window->setFrame(Rect(0, 0, 200, 200));
3674
3675 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3676
3677 // Start hovering with stylus
3678 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3679 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3680 .build());
3681 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3682
3683 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3684 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3685 .build();
3686 // Make this 'hoverExit' event stale
3687 mFakePolicy->setStaleEventTimeout(100ms);
3688 std::this_thread::sleep_for(100ms);
3689
3690 // It shouldn't be dropped by the dispatcher, even though it's stale.
3691 mDispatcher->notifyMotion(hoverExit);
3692 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3693
3694 // Stylus starts hovering again! There should be no crash.
3695 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3696 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3697 .build());
3698 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3699}
3700
3701/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003702 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3703 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3704 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3705 * While the mouse is down, new move events from the touch device should be ignored.
3706 */
3707TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3708 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3709 sp<FakeWindowHandle> spyWindow =
3710 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3711 spyWindow->setFrame(Rect(0, 0, 200, 200));
3712 spyWindow->setTrustedOverlay(true);
3713 spyWindow->setSpy(true);
3714 sp<FakeWindowHandle> window =
3715 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3716 window->setFrame(Rect(0, 0, 200, 200));
3717
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003718 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003719
3720 const int32_t mouseDeviceId = 7;
3721 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003722
3723 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003724 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3725 .deviceId(mouseDeviceId)
3726 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3727 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003728 spyWindow->consumeMotionEvent(
3729 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3730 window->consumeMotionEvent(
3731 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3732
3733 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003734 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3735 .deviceId(touchDeviceId)
3736 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3737 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003738 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3739 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3740 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3741 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3742
Prabir Pradhan678438e2023-04-13 19:32:51 +00003743 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3744 .deviceId(touchDeviceId)
3745 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3746 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003747 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3748 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3749
3750 // Pilfer the stream
3751 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3752 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3753
Prabir Pradhan678438e2023-04-13 19:32:51 +00003754 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3755 .deviceId(touchDeviceId)
3756 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3757 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003758 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3759
3760 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003761 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3762 .deviceId(mouseDeviceId)
3763 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3764 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3765 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003766
3767 spyWindow->consumeMotionEvent(
3768 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3769 spyWindow->consumeMotionEvent(
3770 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3771 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3772
Prabir Pradhan678438e2023-04-13 19:32:51 +00003773 mDispatcher->notifyMotion(
3774 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3775 .deviceId(mouseDeviceId)
3776 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3777 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3778 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3779 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003780 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3781 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3782
3783 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003784 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3785 .deviceId(mouseDeviceId)
3786 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3787 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3788 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003789 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3790 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3791
3792 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003793 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3794 .deviceId(touchDeviceId)
3795 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3796 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003797
3798 // No more events
3799 spyWindow->assertNoEvents();
3800 window->assertNoEvents();
3801}
3802
3803/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003804 * On the display, have a single window, and also an area where there's no window.
3805 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3806 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3807 */
3808TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3809 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3810 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003811 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003812
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003813 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003814
3815 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003816 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003817
3818 mDispatcher->waitForIdle();
3819 window->assertNoEvents();
3820
3821 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003822 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003823 mDispatcher->waitForIdle();
3824 window->consumeMotionDown();
3825}
3826
3827/**
3828 * Same test as above, but instead of touching the empty space, the first touch goes to
3829 * non-touchable window.
3830 */
3831TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3832 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3833 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003834 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003835 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3836 window1->setTouchable(false);
3837 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003838 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003839 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3840
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003841 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003842
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003843 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003844 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003845
3846 mDispatcher->waitForIdle();
3847 window1->assertNoEvents();
3848 window2->assertNoEvents();
3849
3850 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003851 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003852 mDispatcher->waitForIdle();
3853 window2->consumeMotionDown();
3854}
3855
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003856/**
3857 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3858 * to the event time of the first ACTION_DOWN sent to the particular window.
3859 */
3860TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3861 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3862 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003863 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003864 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3865 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003866 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003867 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3868
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003869 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003870
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003871 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003872 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003873 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003874
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003875 const std::unique_ptr<MotionEvent> firstDown =
3876 window1->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
3877 ASSERT_EQ(firstDown->getDownTime(), firstDown->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003878 window2->assertNoEvents();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003879
3880 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003881 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003882 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003883
3884 const std::unique_ptr<MotionEvent> secondDown =
3885 window2->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
3886 ASSERT_EQ(secondDown->getDownTime(), secondDown->getEventTime());
3887 ASSERT_NE(firstDown->getDownTime(), secondDown->getDownTime());
3888 // We currently send MOVE events to all windows receiving a split touch when there is any change
3889 // in the touch state, even when none of the pointers in the split window actually moved.
3890 // Document this behavior in the test.
3891 window1->consumeMotionMove();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003892
3893 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003894 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003895 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003896
3897 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
3898 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003899
3900 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003901 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003902 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003903
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003904 window2->consumeMotionEvent(
3905 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(secondDown->getDownTime())));
3906 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003907
3908 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003909 mDispatcher->notifyMotion(
3910 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003911 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003912
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003913 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
3914 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
3915
3916 // Now add new touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003917 mDispatcher->notifyMotion(
3918 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003919 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003920
3921 window1->consumeMotionEvent(
3922 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(firstDown->getDownTime())));
3923 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003924}
3925
Garfield Tandf26e862020-07-01 20:18:19 -07003926TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003927 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003928 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003929 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003930 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003931 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003932 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003933 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003934
3935 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3936
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003937 mDispatcher->onWindowInfosChanged(
3938 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003939
3940 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003941 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003942 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003943 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3944 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003945 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003946 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003947 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003948
3949 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003950 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003951 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003952 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3953 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003954 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003955 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003956 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3957 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003958
3959 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003960 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003961 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003962 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3963 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003964 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003965 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003966 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3967 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003968
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003969 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003970 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003971 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3972 AINPUT_SOURCE_MOUSE)
3973 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3974 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003975 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003976 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003977 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003978
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003979 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003980 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003981 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3982 AINPUT_SOURCE_MOUSE)
3983 .buttonState(0)
3984 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003985 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003986 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003987 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003988
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003989 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003990 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003991 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3992 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003993 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003994 .build()));
3995 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3996
3997 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003998 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003999 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004000 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4001 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004002 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004003 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004004 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004005
4006 // No more events
4007 windowLeft->assertNoEvents();
4008 windowRight->assertNoEvents();
4009}
4010
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004011/**
4012 * Put two fingers down (and don't release them) and click the mouse button.
4013 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
4014 * currently active gesture should be canceled, and the new one should proceed.
4015 */
4016TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
4017 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4018 sp<FakeWindowHandle> window =
4019 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4020 window->setFrame(Rect(0, 0, 600, 800));
4021
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004022 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004023
4024 const int32_t touchDeviceId = 4;
4025 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004026
4027 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004028 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4029 .deviceId(touchDeviceId)
4030 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4031 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004032
Prabir Pradhan678438e2023-04-13 19:32:51 +00004033 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4034 .deviceId(touchDeviceId)
4035 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4036 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4037 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004038 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4039 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4040
4041 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00004042 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4043 .deviceId(mouseDeviceId)
4044 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4045 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4046 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004047 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
4048 WithPointerCount(2u)));
4049 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4050
Prabir Pradhan678438e2023-04-13 19:32:51 +00004051 mDispatcher->notifyMotion(
4052 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4053 .deviceId(mouseDeviceId)
4054 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4055 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4056 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4057 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004058 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4059
4060 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4061 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004062 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4063 .deviceId(touchDeviceId)
4064 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4065 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4066 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004067 window->assertNoEvents();
4068}
4069
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004070TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
4071 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4072
4073 sp<FakeWindowHandle> spyWindow =
4074 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4075 spyWindow->setFrame(Rect(0, 0, 600, 800));
4076 spyWindow->setTrustedOverlay(true);
4077 spyWindow->setSpy(true);
4078 sp<FakeWindowHandle> window =
4079 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4080 window->setFrame(Rect(0, 0, 600, 800));
4081
4082 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004083 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004084
4085 // Send mouse cursor to the window
4086 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004087 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004088 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4089 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004090 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004091 .build()));
4092
4093 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4094 WithSource(AINPUT_SOURCE_MOUSE)));
4095 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4096 WithSource(AINPUT_SOURCE_MOUSE)));
4097
4098 window->assertNoEvents();
4099 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004100}
4101
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004102TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
4103 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4104
4105 sp<FakeWindowHandle> spyWindow =
4106 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4107 spyWindow->setFrame(Rect(0, 0, 600, 800));
4108 spyWindow->setTrustedOverlay(true);
4109 spyWindow->setSpy(true);
4110 sp<FakeWindowHandle> window =
4111 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4112 window->setFrame(Rect(0, 0, 600, 800));
4113
4114 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004115 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004116
4117 // Send mouse cursor to the window
4118 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004119 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004120 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4121 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004122 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004123 .build()));
4124
4125 // Move mouse cursor
4126 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004127 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004128 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4129 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004130 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004131 .build()));
4132
4133 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4134 WithSource(AINPUT_SOURCE_MOUSE)));
4135 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4136 WithSource(AINPUT_SOURCE_MOUSE)));
4137 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4138 WithSource(AINPUT_SOURCE_MOUSE)));
4139 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4140 WithSource(AINPUT_SOURCE_MOUSE)));
4141 // Touch down on the window
4142 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004143 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004144 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4145 AINPUT_SOURCE_TOUCHSCREEN)
4146 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004147 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004148 .build()));
4149 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4150 WithSource(AINPUT_SOURCE_MOUSE)));
4151 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4152 WithSource(AINPUT_SOURCE_MOUSE)));
4153 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4154 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4155 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4156 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4157
4158 // pilfer the motion, retaining the gesture on the spy window.
4159 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4160 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4161 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4162
4163 // Touch UP on the window
4164 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004165 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004166 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4167 AINPUT_SOURCE_TOUCHSCREEN)
4168 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004169 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004170 .build()));
4171 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4172 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4173
4174 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4175 // to send a new gesture. It should again go to both windows (spy and the window below), just
4176 // like the first gesture did, before pilfering. The window configuration has not changed.
4177
4178 // One more tap - DOWN
4179 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004180 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004181 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4182 AINPUT_SOURCE_TOUCHSCREEN)
4183 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004184 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004185 .build()));
4186 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4187 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4188 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4189 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4190
4191 // Touch UP on the window
4192 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004193 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004194 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4195 AINPUT_SOURCE_TOUCHSCREEN)
4196 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004197 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004198 .build()));
4199 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4200 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4201 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4202 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4203
4204 window->assertNoEvents();
4205 spyWindow->assertNoEvents();
4206}
4207
Garfield Tandf26e862020-07-01 20:18:19 -07004208// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
4209// directly in this test.
4210TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004211 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07004212 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004213 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004214 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004215
4216 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4217
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004218 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004219
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004220 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004221 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004222 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4223 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004224 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004225 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004226 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004227 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004228 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004229 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004230 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4231 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004232 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004233 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004234 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4235 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004236
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004237 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004238 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004239 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4240 AINPUT_SOURCE_MOUSE)
4241 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4242 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004243 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004244 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004245 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004246
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004247 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004248 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004249 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4250 AINPUT_SOURCE_MOUSE)
4251 .buttonState(0)
4252 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004253 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004254 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004255 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004256
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004257 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004258 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004259 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4260 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004261 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004262 .build()));
4263 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
4264
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07004265 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
4266 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
4267 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004268 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004269 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
4270 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004271 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004272 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004273 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004274}
4275
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004276/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004277 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
4278 * is generated.
4279 */
4280TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
4281 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4282 sp<FakeWindowHandle> window =
4283 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4284 window->setFrame(Rect(0, 0, 1200, 800));
4285
4286 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4287
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004288 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004289
4290 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004291 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004292 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4293 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004294 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004295 .build()));
4296 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4297
4298 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004299 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004300 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4301}
4302
4303/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004304 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4305 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004306TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4307 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4308 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004309 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4310 sp<FakeWindowHandle> window =
4311 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4312 window->setFrame(Rect(0, 0, 1200, 800));
4313
4314 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4315
4316 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4317
4318 MotionEventBuilder hoverEnterBuilder =
4319 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4320 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4321 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4322 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4323 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4324 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4325 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4326 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4327 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4328}
4329
4330/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004331 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4332 */
4333TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4334 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4335 sp<FakeWindowHandle> window =
4336 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4337 window->setFrame(Rect(0, 0, 100, 100));
4338
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004339 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004340
4341 const int32_t mouseDeviceId = 7;
4342 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004343
4344 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004345 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4346 .deviceId(mouseDeviceId)
4347 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4348 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004349 window->consumeMotionEvent(
4350 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4351
4352 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004353 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4354 .deviceId(touchDeviceId)
4355 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4356 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004357
4358 window->consumeMotionEvent(
4359 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4360 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4361}
4362
4363/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004364 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004365 * The tap causes a HOVER_EXIT event to be generated because the current event
4366 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004367 */
4368TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4369 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4370 sp<FakeWindowHandle> window =
4371 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4372 window->setFrame(Rect(0, 0, 100, 100));
4373
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004374 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004375 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4376 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4377 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004378 ASSERT_NO_FATAL_FAILURE(
4379 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4380 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004381
4382 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004383 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4384 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4385 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004386 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004387 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4388 WithSource(AINPUT_SOURCE_MOUSE))));
4389
4390 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004391 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4392 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4393
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004394 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4395 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4396 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004397 ASSERT_NO_FATAL_FAILURE(
4398 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4399 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4400}
4401
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004402TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4403 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4404 sp<FakeWindowHandle> windowDefaultDisplay =
4405 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4406 ADISPLAY_ID_DEFAULT);
4407 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4408 sp<FakeWindowHandle> windowSecondDisplay =
4409 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4410 SECOND_DISPLAY_ID);
4411 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4412
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004413 mDispatcher->onWindowInfosChanged(
4414 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004415
4416 // Set cursor position in window in default display and check that hover enter and move
4417 // events are generated.
4418 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004419 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004420 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4421 AINPUT_SOURCE_MOUSE)
4422 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004423 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004424 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004425 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004426
4427 // Remove all windows in secondary display and check that no event happens on window in
4428 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004429 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4430
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004431 windowDefaultDisplay->assertNoEvents();
4432
4433 // Move cursor position in window in default display and check that only hover move
4434 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004435 mDispatcher->onWindowInfosChanged(
4436 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004437 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004438 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004439 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4440 AINPUT_SOURCE_MOUSE)
4441 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004442 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004443 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004444 windowDefaultDisplay->consumeMotionEvent(
4445 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4446 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004447 windowDefaultDisplay->assertNoEvents();
4448}
4449
Garfield Tan00f511d2019-06-12 16:55:40 -07004450TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004451 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004452
4453 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004454 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004455 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004456 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004457 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004458 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004459
4460 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4461
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004462 mDispatcher->onWindowInfosChanged(
4463 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004464
4465 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4466 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004467 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004468 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004469 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004470 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004471 windowRight->assertNoEvents();
4472}
4473
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004474TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004475 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004476 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4477 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004478 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004479
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004480 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004481 setFocusedWindow(window);
4482
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004483 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004484
Prabir Pradhan678438e2023-04-13 19:32:51 +00004485 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004486
4487 // Window should receive key down event.
4488 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4489
4490 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4491 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004492 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004493 window->consumeKeyUp(ADISPLAY_ID_DEFAULT, AKEY_EVENT_FLAG_CANCELED);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004494}
4495
4496TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004497 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004498 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4499 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004500
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004501 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004502
Prabir Pradhan678438e2023-04-13 19:32:51 +00004503 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4504 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004505
4506 // Window should receive motion down event.
4507 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4508
4509 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4510 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004511 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004512 window->consumeMotionEvent(
4513 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004514}
4515
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004516TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4517 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4518 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4519 "Fake Window", ADISPLAY_ID_DEFAULT);
4520
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004521 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004522
4523 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4524 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4525 .build());
4526
4527 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4528
4529 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4530 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4531 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4532
4533 // After the device has been reset, a new hovering stream can be sent to the window
4534 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4535 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4536 .build());
4537 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4538}
4539
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004540TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4541 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004542 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4543 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004544 window->setFocusable(true);
4545
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004546 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004547 setFocusedWindow(window);
4548
4549 window->consumeFocusEvent(true);
4550
Prabir Pradhan678438e2023-04-13 19:32:51 +00004551 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004552 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4553 const nsecs_t injectTime = keyArgs.eventTime;
4554 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004555 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004556 // The dispatching time should be always greater than or equal to intercept key timeout.
4557 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4558 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4559 std::chrono::nanoseconds(interceptKeyTimeout).count());
4560}
4561
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004562/**
4563 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4564 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004565TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4566 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004567 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4568 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004569 window->setFocusable(true);
4570
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004571 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004572 setFocusedWindow(window);
4573
4574 window->consumeFocusEvent(true);
4575
Prabir Pradhan678438e2023-04-13 19:32:51 +00004576 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004577 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004578
4579 // Set a value that's significantly larger than the default consumption timeout. If the
4580 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4581 mFakePolicy->setInterceptKeyTimeout(600ms);
4582 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4583 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004584 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4585}
4586
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004587/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004588 * Two windows. First is a regular window. Second does not overlap with the first, and has
4589 * WATCH_OUTSIDE_TOUCH.
4590 * Both windows are owned by the same UID.
4591 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4592 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4593 */
4594TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4595 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004596 sp<FakeWindowHandle> window =
4597 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004598 window->setFrame(Rect{0, 0, 100, 100});
4599
4600 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004601 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004602 ADISPLAY_ID_DEFAULT);
4603 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4604 outsideWindow->setWatchOutsideTouch(true);
4605 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004606 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004607
4608 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004609 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4610 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4611 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004612 window->consumeMotionDown();
4613 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4614 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4615 outsideWindow->consumeMotionEvent(
4616 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00004617
4618 // Ensure outsideWindow doesn't get any more events for the gesture.
4619 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4620 ADISPLAY_ID_DEFAULT, {PointF{51, 51}}));
4621 window->consumeMotionMove();
4622 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004623}
4624
4625/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004626 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4627 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4628 * ACTION_OUTSIDE event is sent per gesture.
4629 */
4630TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4631 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4632 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004633 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4634 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004635 window->setWatchOutsideTouch(true);
4636 window->setFrame(Rect{0, 0, 100, 100});
4637 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004638 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4639 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004640 secondWindow->setFrame(Rect{100, 100, 200, 200});
4641 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004642 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4643 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004644 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004645 mDispatcher->onWindowInfosChanged(
4646 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004647
4648 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004649 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4650 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4651 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004652 window->assertNoEvents();
4653 secondWindow->assertNoEvents();
4654
4655 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4656 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004657 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4658 ADISPLAY_ID_DEFAULT,
4659 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004660 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4661 window->consumeMotionEvent(
4662 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004663 secondWindow->consumeMotionDown();
4664 thirdWindow->assertNoEvents();
4665
4666 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4667 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004668 mDispatcher->notifyMotion(
4669 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4670 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004671 window->assertNoEvents();
4672 secondWindow->consumeMotionMove();
4673 thirdWindow->consumeMotionDown();
4674}
4675
Prabir Pradhan814fe082022-07-22 20:22:18 +00004676TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4677 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004678 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4679 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004680 window->setFocusable(true);
4681
Patrick Williamsd828f302023-04-28 17:52:08 -05004682 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004683 setFocusedWindow(window);
4684
4685 window->consumeFocusEvent(true);
4686
Prabir Pradhan678438e2023-04-13 19:32:51 +00004687 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4688 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4689 mDispatcher->notifyKey(keyDown);
4690 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004691
4692 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4693 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4694
4695 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004696 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004697
4698 window->consumeFocusEvent(false);
4699
Prabir Pradhan678438e2023-04-13 19:32:51 +00004700 mDispatcher->notifyKey(keyDown);
4701 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004702 window->assertNoEvents();
4703}
4704
Arthur Hung96483742022-11-15 03:30:48 +00004705TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4706 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4707 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4708 "Fake Window", ADISPLAY_ID_DEFAULT);
4709 // Ensure window is non-split and have some transform.
4710 window->setPreventSplitting(true);
4711 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004712 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004713
4714 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004715 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004716 {50, 50}))
4717 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4718 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4719
4720 const MotionEvent secondFingerDownEvent =
4721 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4722 .displayId(ADISPLAY_ID_DEFAULT)
4723 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004724 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4725 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004726 .build();
4727 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004728 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004729 InputEventInjectionSync::WAIT_FOR_RESULT))
4730 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4731
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004732 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
4733 ASSERT_NE(nullptr, event);
4734 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4735 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4736 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4737 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4738 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
Arthur Hung96483742022-11-15 03:30:48 +00004739}
4740
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004741/**
4742 * Two windows: a splittable and a non-splittable.
4743 * The non-splittable window shouldn't receive any "incomplete" gestures.
4744 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4745 * The second pointer should be dropped because the initial window is splittable, so it won't get
4746 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4747 * "incomplete" gestures.
4748 */
4749TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4750 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4751 sp<FakeWindowHandle> leftWindow =
4752 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4753 ADISPLAY_ID_DEFAULT);
4754 leftWindow->setPreventSplitting(false);
4755 leftWindow->setFrame(Rect(0, 0, 100, 100));
4756 sp<FakeWindowHandle> rightWindow =
4757 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4758 ADISPLAY_ID_DEFAULT);
4759 rightWindow->setPreventSplitting(true);
4760 rightWindow->setFrame(Rect(100, 100, 200, 200));
4761 mDispatcher->onWindowInfosChanged(
4762 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4763
4764 // Touch down on left, splittable window
4765 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4766 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4767 .build());
4768 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4769
4770 mDispatcher->notifyMotion(
4771 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4772 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4773 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4774 .build());
4775 leftWindow->assertNoEvents();
4776 rightWindow->assertNoEvents();
4777}
4778
Harry Cuttsb166c002023-05-09 13:06:05 +00004779TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4780 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4781 sp<FakeWindowHandle> window =
4782 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4783 window->setFrame(Rect(0, 0, 400, 400));
4784 sp<FakeWindowHandle> trustedOverlay =
4785 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4786 ADISPLAY_ID_DEFAULT);
4787 trustedOverlay->setSpy(true);
4788 trustedOverlay->setTrustedOverlay(true);
4789
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004790 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004791
4792 // Start a three-finger touchpad swipe
4793 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4794 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4795 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4796 .build());
4797 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4798 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4799 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4800 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4801 .build());
4802 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4803 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4804 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4805 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4806 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4807 .build());
4808
4809 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4810 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4811 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4812
4813 // Move the swipe a bit
4814 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4815 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4816 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4817 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4818 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4819 .build());
4820
4821 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4822
4823 // End the swipe
4824 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4825 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4826 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4827 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4828 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4829 .build());
4830 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4831 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4832 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4833 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4834 .build());
4835 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4836 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4837 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4838 .build());
4839
4840 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4841 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4842 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4843
4844 window->assertNoEvents();
4845}
4846
4847TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4848 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4849 sp<FakeWindowHandle> window =
4850 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4851 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004852 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004853
4854 // Start a three-finger touchpad swipe
4855 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4856 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4857 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4858 .build());
4859 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4860 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4861 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4862 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4863 .build());
4864 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4865 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4866 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4867 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4868 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4869 .build());
4870
4871 // Move the swipe a bit
4872 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4873 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4874 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4875 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4876 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4877 .build());
4878
4879 // End the swipe
4880 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4881 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4882 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4883 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4884 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4885 .build());
4886 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4887 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4888 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4889 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4890 .build());
4891 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4892 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4893 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4894 .build());
4895
4896 window->assertNoEvents();
4897}
4898
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004899/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004900 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4901 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004902 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004903 */
4904TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4905 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4906 sp<FakeWindowHandle> window =
4907 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4908 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004909 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004910
4911 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4912 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4913 .downTime(baseTime + 10)
4914 .eventTime(baseTime + 10)
4915 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4916 .build());
4917
4918 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4919
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004920 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004921 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004922
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004923 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004924
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004925 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4926 .downTime(baseTime + 10)
4927 .eventTime(baseTime + 30)
4928 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4929 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4930 .build());
4931
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004932 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4933
4934 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004935 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4936 .downTime(baseTime + 10)
4937 .eventTime(baseTime + 40)
4938 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4939 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4940 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004941
4942 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4943
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004944 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4945 .downTime(baseTime + 10)
4946 .eventTime(baseTime + 50)
4947 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4948 .build());
4949
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004950 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4951
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004952 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4953 .downTime(baseTime + 60)
4954 .eventTime(baseTime + 60)
4955 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4956 .build());
4957
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004958 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004959}
4960
4961/**
Hu Guo771a7692023-09-17 20:51:08 +08004962 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4963 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4964 * its coordinates should be converted by the transform of the windows of target screen.
4965 */
4966TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4967 // This case will create a window and a spy window on the default display and mirror
4968 // window on the second display. cancel event is sent through spy window pilferPointers
4969 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4970
4971 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4972 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4973 spyWindowDefaultDisplay->setTrustedOverlay(true);
4974 spyWindowDefaultDisplay->setSpy(true);
4975
4976 sp<FakeWindowHandle> windowDefaultDisplay =
4977 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4978 ADISPLAY_ID_DEFAULT);
4979 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4980
4981 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4982 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4983
4984 // Add the windows to the dispatcher
4985 mDispatcher->onWindowInfosChanged(
4986 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4987 *windowSecondDisplay->getInfo()},
4988 {},
4989 0,
4990 0});
4991
4992 // Send down to ADISPLAY_ID_DEFAULT
4993 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4994 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4995 {100, 100}))
4996 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4997
4998 spyWindowDefaultDisplay->consumeMotionDown();
4999 windowDefaultDisplay->consumeMotionDown();
5000
5001 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
5002
5003 // windowDefaultDisplay gets cancel
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005004 std::unique_ptr<MotionEvent> event = windowDefaultDisplay->consumeMotionEvent();
5005 ASSERT_NE(nullptr, event);
5006 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
Hu Guo771a7692023-09-17 20:51:08 +08005007
5008 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
5009 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
5010 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
5011 // SECOND_DISPLAY_ID, the x and y coordinates are 200
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005012 EXPECT_EQ(100, event->getX(0));
5013 EXPECT_EQ(100, event->getY(0));
Hu Guo771a7692023-09-17 20:51:08 +08005014}
5015
5016/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005017 * Ensure the correct coordinate spaces are used by InputDispatcher.
5018 *
5019 * InputDispatcher works in the display space, so its coordinate system is relative to the display
5020 * panel. Windows get events in the window space, and get raw coordinates in the logical display
5021 * space.
5022 */
5023class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
5024public:
5025 void SetUp() override {
5026 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005027 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005028 }
5029
5030 void addDisplayInfo(int displayId, const ui::Transform& transform) {
5031 gui::DisplayInfo info;
5032 info.displayId = displayId;
5033 info.transform = transform;
5034 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05005035 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005036 }
5037
5038 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
5039 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05005040 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005041 }
5042
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005043 void removeAllWindowsAndDisplays() {
5044 mDisplayInfos.clear();
5045 mWindowInfos.clear();
5046 }
5047
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005048 // Set up a test scenario where the display has a scaled projection and there are two windows
5049 // on the display.
5050 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
5051 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
5052 // respectively.
5053 ui::Transform displayTransform;
5054 displayTransform.set(2, 0, 0, 4);
5055 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5056
5057 std::shared_ptr<FakeApplicationHandle> application =
5058 std::make_shared<FakeApplicationHandle>();
5059
5060 // Add two windows to the display. Their frames are represented in the display space.
5061 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005062 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5063 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005064 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
5065 addWindow(firstWindow);
5066
5067 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005068 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5069 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005070 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
5071 addWindow(secondWindow);
5072 return {std::move(firstWindow), std::move(secondWindow)};
5073 }
5074
5075private:
5076 std::vector<gui::DisplayInfo> mDisplayInfos;
5077 std::vector<gui::WindowInfo> mWindowInfos;
5078};
5079
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005080TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005081 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5082 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005083 // selected so that if the hit test was performed with the point and the bounds being in
5084 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005085 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5086 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5087 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005088
5089 firstWindow->consumeMotionDown();
5090 secondWindow->assertNoEvents();
5091}
5092
5093// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
5094// the event should be treated as being in the logical display space.
5095TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
5096 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5097 // Send down to the first window. The point is represented in the logical display space. The
5098 // point is selected so that if the hit test was done in logical display space, then it would
5099 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005100 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005101 PointF{75 * 2, 55 * 4});
5102
5103 firstWindow->consumeMotionDown();
5104 secondWindow->assertNoEvents();
5105}
5106
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005107// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
5108// event should be treated as being in the logical display space.
5109TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
5110 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5111
5112 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5113 ui::Transform injectedEventTransform;
5114 injectedEventTransform.set(matrix);
5115 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
5116 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
5117
5118 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5119 .displayId(ADISPLAY_ID_DEFAULT)
5120 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005121 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005122 .x(untransformedPoint.x)
5123 .y(untransformedPoint.y))
5124 .build();
5125 event.transform(matrix);
5126
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005127 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005128 InputEventInjectionSync::WAIT_FOR_RESULT);
5129
5130 firstWindow->consumeMotionDown();
5131 secondWindow->assertNoEvents();
5132}
5133
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005134TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
5135 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5136
5137 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005138 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5139 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5140 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005141
5142 firstWindow->assertNoEvents();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005143 std::unique_ptr<MotionEvent> event = secondWindow->consumeMotionEvent();
5144 ASSERT_NE(nullptr, event);
5145 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005146
5147 // Ensure that the events from the "getRaw" API are in logical display coordinates.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005148 EXPECT_EQ(300, event->getRawX(0));
5149 EXPECT_EQ(880, event->getRawY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005150
5151 // Ensure that the x and y values are in the window's coordinate space.
5152 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
5153 // the logical display space. This will be the origin of the window space.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005154 EXPECT_EQ(100, event->getX(0));
5155 EXPECT_EQ(80, event->getY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005156}
5157
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005158TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
5159 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5160 // The monitor will always receive events in the logical display's coordinate space, because
5161 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00005162 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005163
5164 // Send down to the first window.
5165 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5166 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5167 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5168 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5169
5170 // Second pointer goes down on second window.
5171 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5172 ADISPLAY_ID_DEFAULT,
5173 {PointF{50, 100}, PointF{150, 220}}));
5174 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
5175 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
5176 {1, PointF{300, 880}}};
5177 monitor.consumeMotionEvent(
5178 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
5179
5180 mDispatcher->cancelCurrentTouch();
5181
5182 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5183 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
5184 monitor.consumeMotionEvent(
5185 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
5186}
5187
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005188TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
5189 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5190
5191 // Send down to the first window.
5192 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5193 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5194 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5195
5196 // The pointer is transferred to the second window, and the second window receives it in the
5197 // correct coordinate space.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005198 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005199 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5200 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
5201}
5202
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005203TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
5204 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5205
5206 // Send hover move to the second window, and ensure it shows up as hover enter.
5207 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5208 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5209 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5210 WithCoords(100, 80), WithRawCoords(300, 880)));
5211
5212 // Touch down at the same location and ensure a hover exit is synthesized.
5213 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5214 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5215 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5216 WithRawCoords(300, 880)));
5217 secondWindow->consumeMotionEvent(
5218 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5219 secondWindow->assertNoEvents();
5220 firstWindow->assertNoEvents();
5221}
5222
Prabir Pradhan453ae732023-10-13 14:30:14 +00005223// Same as above, but while the window is being mirrored.
5224TEST_F(InputDispatcherDisplayProjectionTest,
5225 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
5226 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5227
5228 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5229 ui::Transform secondDisplayTransform;
5230 secondDisplayTransform.set(matrix);
5231 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5232
5233 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5234 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5235 addWindow(secondWindowClone);
5236
5237 // Send hover move to the second window, and ensure it shows up as hover enter.
5238 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5239 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5240 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5241 WithCoords(100, 80), WithRawCoords(300, 880)));
5242
5243 // Touch down at the same location and ensure a hover exit is synthesized for the correct
5244 // display.
5245 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5246 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5247 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5248 WithRawCoords(300, 880)));
5249 secondWindow->consumeMotionEvent(
5250 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5251 secondWindow->assertNoEvents();
5252 firstWindow->assertNoEvents();
5253}
5254
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005255TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
5256 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5257
5258 // Send hover enter to second window
5259 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5260 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5261 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5262 WithCoords(100, 80), WithRawCoords(300, 880)));
5263
5264 mDispatcher->cancelCurrentTouch();
5265
5266 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5267 WithRawCoords(300, 880)));
5268 secondWindow->assertNoEvents();
5269 firstWindow->assertNoEvents();
5270}
5271
Prabir Pradhan453ae732023-10-13 14:30:14 +00005272// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00005273TEST_F(InputDispatcherDisplayProjectionTest,
5274 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
5275 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5276
5277 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5278 ui::Transform secondDisplayTransform;
5279 secondDisplayTransform.set(matrix);
5280 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5281
5282 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5283 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5284 addWindow(secondWindowClone);
5285
5286 // Send hover enter to second window
5287 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5288 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5289 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5290 WithCoords(100, 80), WithRawCoords(300, 880),
5291 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5292
5293 mDispatcher->cancelCurrentTouch();
5294
5295 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
5296 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5297 WithRawCoords(300, 880),
5298 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5299 secondWindow->assertNoEvents();
5300 firstWindow->assertNoEvents();
5301}
5302
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005303/** Ensure consistent behavior of InputDispatcher in all orientations. */
5304class InputDispatcherDisplayOrientationFixture
5305 : public InputDispatcherDisplayProjectionTest,
5306 public ::testing::WithParamInterface<ui::Rotation> {};
5307
5308// This test verifies the touchable region of a window for all rotations of the display by tapping
5309// in different locations on the display, specifically points close to the four corners of a
5310// window.
5311TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
5312 constexpr static int32_t displayWidth = 400;
5313 constexpr static int32_t displayHeight = 800;
5314
5315 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5316
5317 const auto rotation = GetParam();
5318
5319 // Set up the display with the specified rotation.
5320 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5321 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5322 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5323 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5324 logicalDisplayWidth, logicalDisplayHeight);
5325 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5326
5327 // Create a window with its bounds determined in the logical display.
5328 const Rect frameInLogicalDisplay(100, 100, 200, 300);
5329 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
5330 sp<FakeWindowHandle> window =
5331 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5332 window->setFrame(frameInDisplay, displayTransform);
5333 addWindow(window);
5334
5335 // The following points in logical display space should be inside the window.
5336 static const std::array<vec2, 4> insidePoints{
5337 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5338 for (const auto pointInsideWindow : insidePoints) {
5339 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
5340 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005341 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5342 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5343 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005344 window->consumeMotionDown();
5345
Prabir Pradhan678438e2023-04-13 19:32:51 +00005346 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5347 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5348 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005349 window->consumeMotionUp();
5350 }
5351
5352 // The following points in logical display space should be outside the window.
5353 static const std::array<vec2, 5> outsidePoints{
5354 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
5355 for (const auto pointOutsideWindow : outsidePoints) {
5356 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
5357 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005358 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5359 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5360 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005361
Prabir Pradhan678438e2023-04-13 19:32:51 +00005362 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5363 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5364 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005365 }
5366 window->assertNoEvents();
5367}
5368
5369// Run the precision tests for all rotations.
5370INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
5371 InputDispatcherDisplayOrientationFixture,
5372 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
5373 ui::ROTATION_270),
5374 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
5375 return ftl::enum_string(testParamInfo.param);
5376 });
5377
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005378using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
5379 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005380
5381class TransferTouchFixture : public InputDispatcherTest,
5382 public ::testing::WithParamInterface<TransferFunction> {};
5383
5384TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07005385 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005386
5387 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005388 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005389 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5390 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005391 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005392 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005393 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5394 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005395 sp<FakeWindowHandle> wallpaper =
5396 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
5397 wallpaper->setIsWallpaper(true);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005398 // Add the windows to the dispatcher, and ensure the first window is focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005399 mDispatcher->onWindowInfosChanged(
5400 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Prabir Pradhan65455c72024-02-13 21:46:41 +00005401 setFocusedWindow(firstWindow);
5402 firstWindow->consumeFocusEvent(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005403
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));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005407
Svet Ganov5d3bc372020-01-26 23:11:07 -08005408 // Only the first window should get the down event
5409 firstWindow->consumeMotionDown();
5410 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005411 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005412 // Dispatcher reports pointer down outside focus for the wallpaper
5413 mFakePolicy->assertOnPointerDownEquals(wallpaper->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08005414
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005415 // Transfer touch to the second window
5416 TransferFunction f = GetParam();
5417 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5418 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005419 // The first window gets cancel and the second gets down
5420 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005421 secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005422 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005423 // There should not be any changes to the focused window when transferring touch
5424 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertOnPointerDownWasNotCalled());
Svet Ganov5d3bc372020-01-26 23:11:07 -08005425
5426 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005427 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5428 ADISPLAY_ID_DEFAULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +00005429 // The first window gets no events and the second gets up
Svet Ganov5d3bc372020-01-26 23:11:07 -08005430 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005431 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005432 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005433}
5434
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005435/**
Prabir Pradhan367f3432024-02-13 23:05:58 +00005436 * When 'transferTouchGesture' API is invoked, dispatcher needs to find the "best" window to take
5437 * touch from. When we have spy windows, there are several windows to choose from: either spy, or
5438 * the 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005439 * natural to the user.
5440 * In this test, we are sending a pointer to both spy window and first window. We then try to
5441 * transfer touch to the second window. The dispatcher should identify the first window as the
5442 * one that should lose the gesture, and therefore the action should be to move the gesture from
5443 * the first window to the second.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005444 * The main goal here is to test the behaviour of 'transferTouchGesture' API, but it's still valid
5445 * to test the other API, as well.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005446 */
5447TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5448 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5449
5450 // Create a couple of windows + a spy window
5451 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005452 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005453 spyWindow->setTrustedOverlay(true);
5454 spyWindow->setSpy(true);
5455 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005456 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005457 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005458 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005459
5460 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005461 mDispatcher->onWindowInfosChanged(
5462 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005463
5464 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005465 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5466 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005467 // Only the first window and spy should get the down event
5468 spyWindow->consumeMotionDown();
5469 firstWindow->consumeMotionDown();
5470
5471 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
Prabir Pradhan367f3432024-02-13 23:05:58 +00005472 // if f === 'transferTouchGesture'.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005473 TransferFunction f = GetParam();
5474 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5475 ASSERT_TRUE(success);
5476 // The first window gets cancel and the second gets down
5477 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005478 secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005479
5480 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005481 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5482 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005483 // The first window gets no events and the second+spy get up
5484 firstWindow->assertNoEvents();
5485 spyWindow->consumeMotionUp();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005486 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005487}
5488
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005489TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005490 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005491
5492 PointF touchPoint = {10, 10};
5493
5494 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005495 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005496 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5497 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005498 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005499 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005500 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5501 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005502 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005503
5504 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005505 mDispatcher->onWindowInfosChanged(
5506 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005507
5508 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005509 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5510 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5511 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005512 // Only the first window should get the down event
5513 firstWindow->consumeMotionDown();
5514 secondWindow->assertNoEvents();
5515
5516 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005517 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5518 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005519 // Only the first window should get the pointer down event
5520 firstWindow->consumeMotionPointerDown(1);
5521 secondWindow->assertNoEvents();
5522
5523 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005524 TransferFunction f = GetParam();
5525 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5526 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005527 // The first window gets cancel and the second gets down and pointer down
5528 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005529 secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
5530 secondWindow->consumeMotionPointerDown(1, ADISPLAY_ID_DEFAULT,
5531 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005532
5533 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005534 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5535 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005536 // The first window gets nothing and the second gets pointer up
5537 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005538 secondWindow->consumeMotionPointerUp(1, ADISPLAY_ID_DEFAULT,
5539 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005540
5541 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005542 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5543 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005544 // The first window gets nothing and the second gets up
5545 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005546 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005547}
5548
Arthur Hungc539dbb2022-12-08 07:45:36 +00005549TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5550 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5551
5552 // Create a couple of windows
5553 sp<FakeWindowHandle> firstWindow =
5554 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5555 ADISPLAY_ID_DEFAULT);
5556 firstWindow->setDupTouchToWallpaper(true);
5557 sp<FakeWindowHandle> secondWindow =
5558 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5559 ADISPLAY_ID_DEFAULT);
5560 secondWindow->setDupTouchToWallpaper(true);
5561
5562 sp<FakeWindowHandle> wallpaper1 =
5563 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5564 wallpaper1->setIsWallpaper(true);
5565
5566 sp<FakeWindowHandle> wallpaper2 =
5567 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5568 wallpaper2->setIsWallpaper(true);
5569 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005570 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5571 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5572 {},
5573 0,
5574 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005575
5576 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005577 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5578 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005579
5580 // Only the first window should get the down event
5581 firstWindow->consumeMotionDown();
5582 secondWindow->assertNoEvents();
5583 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5584 wallpaper2->assertNoEvents();
5585
5586 // Transfer touch focus to the second window
5587 TransferFunction f = GetParam();
5588 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5589 ASSERT_TRUE(success);
5590
5591 // The first window gets cancel and the second gets down
5592 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005593 secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005594 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005595 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5596 expectedWallpaperFlags | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005597
5598 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005599 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5600 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005601 // The first window gets no events and the second gets up
5602 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005603 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005604 wallpaper1->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005605 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT,
5606 expectedWallpaperFlags | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005607}
5608
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005609// For the cases of single pointer touch and two pointers non-split touch, the api's
Prabir Pradhan367f3432024-02-13 23:05:58 +00005610// 'transferTouchGesture' and 'transferTouchOnDisplay' are equivalent in behaviour. They only differ
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005611// for the case where there are multiple pointers split across several windows.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005612INSTANTIATE_TEST_SUITE_P(
5613 InputDispatcherTransferFunctionTests, TransferTouchFixture,
5614 ::testing::Values(
5615 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> /*ignored*/,
5616 sp<IBinder> destChannelToken) {
5617 return dispatcher->transferTouchOnDisplay(destChannelToken,
5618 ADISPLAY_ID_DEFAULT);
5619 },
5620 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> from,
5621 sp<IBinder> to) {
5622 return dispatcher->transferTouchGesture(from, to,
5623 /*isDragAndDrop=*/false);
5624 }));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005625
Prabir Pradhan367f3432024-02-13 23:05:58 +00005626TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005627 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005628
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005629 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005630 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5631 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005632 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005633
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005634 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005635 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5636 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005637 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005638
5639 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005640 mDispatcher->onWindowInfosChanged(
5641 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005642
5643 PointF pointInFirst = {300, 200};
5644 PointF pointInSecond = {300, 600};
5645
5646 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005647 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5648 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5649 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005650 // Only the first window should get the down event
5651 firstWindow->consumeMotionDown();
5652 secondWindow->assertNoEvents();
5653
5654 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005655 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5656 ADISPLAY_ID_DEFAULT,
5657 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005658 // The first window gets a move and the second a down
5659 firstWindow->consumeMotionMove();
5660 secondWindow->consumeMotionDown();
5661
Prabir Pradhan367f3432024-02-13 23:05:58 +00005662 // Transfer touch to the second window
5663 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08005664 // The first window gets cancel and the new gets pointer down (it already saw down)
5665 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005666 secondWindow->consumeMotionPointerDown(1, ADISPLAY_ID_DEFAULT,
5667 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005668
5669 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005670 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5671 ADISPLAY_ID_DEFAULT,
5672 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005673 // The first window gets nothing and the second gets pointer up
5674 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005675 secondWindow->consumeMotionPointerUp(1, ADISPLAY_ID_DEFAULT,
5676 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005677
5678 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005679 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5680 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005681 // The first window gets nothing and the second gets up
5682 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005683 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005684}
5685
Prabir Pradhan367f3432024-02-13 23:05:58 +00005686// Same as TransferTouch_TwoPointersSplitTouch, but using 'transferTouchOnDisplay' api.
5687// Unlike 'transferTouchGesture', calling 'transferTouchOnDisplay' when there are two windows
5688// receiving touch is not supported, so the touch should continue on those windows and the
5689// transferred-to window should get nothing.
5690TEST_F(InputDispatcherTest, TransferTouchOnDisplay_TwoPointersSplitTouch) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005691 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5692
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005693 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005694 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5695 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005696 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005697
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005698 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005699 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5700 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005701 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005702
5703 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005704 mDispatcher->onWindowInfosChanged(
5705 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005706
5707 PointF pointInFirst = {300, 200};
5708 PointF pointInSecond = {300, 600};
5709
5710 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005711 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5712 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5713 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005714 // Only the first window should get the down event
5715 firstWindow->consumeMotionDown();
5716 secondWindow->assertNoEvents();
5717
5718 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005719 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5720 ADISPLAY_ID_DEFAULT,
5721 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005722 // The first window gets a move and the second a down
5723 firstWindow->consumeMotionMove();
5724 secondWindow->consumeMotionDown();
5725
5726 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005727 const bool transferred =
Prabir Pradhan367f3432024-02-13 23:05:58 +00005728 mDispatcher->transferTouchOnDisplay(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
5729 // The 'transferTouchOnDisplay' call should not succeed, because there are 2 touched windows
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005730 ASSERT_FALSE(transferred);
5731 firstWindow->assertNoEvents();
5732 secondWindow->assertNoEvents();
5733
5734 // The rest of the dispatch should proceed as normal
5735 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005736 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5737 ADISPLAY_ID_DEFAULT,
5738 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005739 // The first window gets MOVE and the second gets pointer up
5740 firstWindow->consumeMotionMove();
5741 secondWindow->consumeMotionUp();
5742
5743 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005744 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5745 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005746 // The first window gets nothing and the second gets up
5747 firstWindow->consumeMotionUp();
5748 secondWindow->assertNoEvents();
5749}
5750
Arthur Hungabbb9d82021-09-01 14:52:30 +00005751// This case will create two windows and one mirrored window on the default display and mirror
Prabir Pradhan367f3432024-02-13 23:05:58 +00005752// two windows on the second display. It will test if 'transferTouchGesture' works fine if we put
Arthur Hungabbb9d82021-09-01 14:52:30 +00005753// the windows info of second display before default display.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005754TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00005755 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5756 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005757 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005758 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005759 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005760 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005761 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005762
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005763 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005764 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005765
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005766 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005767 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005768
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005769 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005770 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005771
5772 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005773 mDispatcher->onWindowInfosChanged(
5774 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5775 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5776 *secondWindowInPrimary->getInfo()},
5777 {},
5778 0,
5779 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005780
5781 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005782 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005783 {50, 50}))
5784 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5785
5786 // Window should receive motion event.
5787 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5788
Prabir Pradhan367f3432024-02-13 23:05:58 +00005789 // Transfer touch
5790 ASSERT_TRUE(mDispatcher->transferTouchGesture(firstWindowInPrimary->getToken(),
5791 secondWindowInPrimary->getToken()));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005792 // The first window gets cancel.
5793 firstWindowInPrimary->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005794 secondWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5795 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005796
5797 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005798 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005799 ADISPLAY_ID_DEFAULT, {150, 50}))
5800 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5801 firstWindowInPrimary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005802 secondWindowInPrimary->consumeMotionMove(ADISPLAY_ID_DEFAULT,
5803 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005804
5805 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005806 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005807 {150, 50}))
5808 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5809 firstWindowInPrimary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005810 secondWindowInPrimary->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005811}
5812
Prabir Pradhan367f3432024-02-13 23:05:58 +00005813// Same as TransferTouch_CloneSurface, but this touch on the secondary display and use
5814// 'transferTouchOnDisplay' api.
5815TEST_F(InputDispatcherTest, TransferTouchOnDisplay_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00005816 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5817 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005818 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005819 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005820 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005821 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005822 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005823
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005824 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005825 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005826
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005827 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005828 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005829
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005830 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005831 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005832
5833 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005834 mDispatcher->onWindowInfosChanged(
5835 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5836 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5837 *secondWindowInPrimary->getInfo()},
5838 {},
5839 0,
5840 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005841
5842 // Touch on second display.
5843 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005844 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5845 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005846 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5847
5848 // Window should receive motion event.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005849 firstWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005850
5851 // Transfer touch focus
Prabir Pradhan367f3432024-02-13 23:05:58 +00005852 ASSERT_TRUE(mDispatcher->transferTouchOnDisplay(secondWindowInSecondary->getToken(),
5853 SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005854
5855 // The first window gets cancel.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005856 firstWindowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005857 secondWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID,
5858 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005859
5860 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005861 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005862 SECOND_DISPLAY_ID, {150, 50}))
5863 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005864 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005865 secondWindowInSecondary->consumeMotionMove(SECOND_DISPLAY_ID,
5866 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005867
5868 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005869 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005870 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005871 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005872 secondWindowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005873}
5874
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005875TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005876 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005877 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5878 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005879
Vishnu Nair47074b82020-08-14 11:54:47 -07005880 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005881 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005882 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005883
5884 window->consumeFocusEvent(true);
5885
Prabir Pradhan678438e2023-04-13 19:32:51 +00005886 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005887
5888 // Window should receive key down event.
5889 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005890
5891 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005892 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005893 mFakePolicy->assertUserActivityPoked();
5894}
5895
5896TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5897 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5898 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5899 "Fake Window", ADISPLAY_ID_DEFAULT);
5900
5901 window->setDisableUserActivity(true);
5902 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005903 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005904 setFocusedWindow(window);
5905
5906 window->consumeFocusEvent(true);
5907
5908 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5909
5910 // Window should receive key down event.
5911 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5912
5913 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005914 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005915 mFakePolicy->assertUserActivityNotPoked();
5916}
5917
5918TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5919 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5920 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5921 "Fake Window", ADISPLAY_ID_DEFAULT);
5922
5923 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005924 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005925 setFocusedWindow(window);
5926
5927 window->consumeFocusEvent(true);
5928
5929 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5930 mDispatcher->waitForIdle();
5931
5932 // System key is not passed down
5933 window->assertNoEvents();
5934
5935 // Should have poked user activity
5936 mFakePolicy->assertUserActivityPoked();
5937}
5938
5939TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5940 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5941 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5942 "Fake Window", ADISPLAY_ID_DEFAULT);
5943
5944 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005945 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005946 setFocusedWindow(window);
5947
5948 window->consumeFocusEvent(true);
5949
5950 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5951 mDispatcher->waitForIdle();
5952
5953 // System key is not passed down
5954 window->assertNoEvents();
5955
5956 // Should have poked user activity
5957 mFakePolicy->assertUserActivityPoked();
5958}
5959
5960TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5961 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5962 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5963 "Fake Window", ADISPLAY_ID_DEFAULT);
5964
5965 window->setDisableUserActivity(true);
5966 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005967 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005968 setFocusedWindow(window);
5969
5970 window->consumeFocusEvent(true);
5971
5972 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5973 mDispatcher->waitForIdle();
5974
5975 // System key is not passed down
5976 window->assertNoEvents();
5977
5978 // Should have poked user activity
5979 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005980}
5981
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005982TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5983 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5984 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5985 "Fake Window", ADISPLAY_ID_DEFAULT);
5986
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005987 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005988
5989 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005990 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005991 ADISPLAY_ID_DEFAULT, {100, 100}))
5992 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5993
5994 window->consumeMotionEvent(
5995 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5996
5997 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005998 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005999 mFakePolicy->assertUserActivityPoked();
6000}
6001
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006002TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006003 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006004 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6005 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006006
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006007 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006008
Prabir Pradhan678438e2023-04-13 19:32:51 +00006009 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006010 mDispatcher->waitForIdle();
6011
6012 window->assertNoEvents();
6013}
6014
6015// If a window is touchable, but does not have focus, it should receive motion events, but not keys
6016TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07006017 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006018 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6019 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006020
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006021 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006022
6023 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00006024 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006025 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00006026 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6027 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006028
6029 // Window should receive only the motion event
6030 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6031 window->assertNoEvents(); // Key event or focus event will not be received
6032}
6033
arthurhungea3f4fc2020-12-21 23:18:53 +08006034TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
6035 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6036
arthurhungea3f4fc2020-12-21 23:18:53 +08006037 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006038 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
6039 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08006040 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08006041
arthurhungea3f4fc2020-12-21 23:18:53 +08006042 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006043 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
6044 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08006045 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08006046
6047 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006048 mDispatcher->onWindowInfosChanged(
6049 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08006050
6051 PointF pointInFirst = {300, 200};
6052 PointF pointInSecond = {300, 600};
6053
6054 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006055 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6056 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6057 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08006058 // Only the first window should get the down event
6059 firstWindow->consumeMotionDown();
6060 secondWindow->assertNoEvents();
6061
6062 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006063 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6064 ADISPLAY_ID_DEFAULT,
6065 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08006066 // The first window gets a move and the second a down
6067 firstWindow->consumeMotionMove();
6068 secondWindow->consumeMotionDown();
6069
6070 // Send pointer cancel to the second window
6071 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006072 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08006073 {pointInFirst, pointInSecond});
6074 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00006075 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08006076 // The first window gets move and the second gets cancel.
6077 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
6078 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
6079
6080 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00006081 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6082 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08006083 // The first window gets up and the second gets nothing.
6084 firstWindow->consumeMotionUp();
6085 secondWindow->assertNoEvents();
6086}
6087
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006088TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
6089 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6090
6091 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006092 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006093 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006094 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
6095 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
6096 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
6097
Harry Cutts33476232023-01-30 19:57:29 +00006098 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006099 window->assertNoEvents();
6100 mDispatcher->waitForIdle();
6101}
6102
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006103using InputDispatcherMonitorTest = InputDispatcherTest;
6104
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006105/**
6106 * Two entities that receive touch: A window, and a global monitor.
6107 * The touch goes to the window, and then the window disappears.
6108 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
6109 * for the monitor, as well.
6110 * 1. foregroundWindow
6111 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
6112 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006113TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006114 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6115 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006116 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006117
Prabir Pradhanfb549072023-10-05 19:17:36 +00006118 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006119
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006120 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006121 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006122 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006123 {100, 200}))
6124 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6125
6126 // Both the foreground window and the global monitor should receive the touch down
6127 window->consumeMotionDown();
6128 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6129
6130 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006131 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006132 ADISPLAY_ID_DEFAULT, {110, 200}))
6133 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6134
6135 window->consumeMotionMove();
6136 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6137
6138 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006139 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006140 window->consumeMotionCancel();
6141 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
6142
6143 // If more events come in, there will be no more foreground window to send them to. This will
6144 // cause a cancel for the monitor, as well.
6145 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006146 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006147 ADISPLAY_ID_DEFAULT, {120, 200}))
6148 << "Injection should fail because the window was removed";
6149 window->assertNoEvents();
6150 // Global monitor now gets the cancel
6151 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6152}
6153
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006154TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07006155 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006156 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6157 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006158 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006159
Prabir Pradhanfb549072023-10-05 19:17:36 +00006160 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006161
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006162 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006163 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006164 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00006165 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006166 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006167}
6168
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006169TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00006170 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006171
Chris Yea209fde2020-07-22 13:54:51 -07006172 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006173 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6174 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006175 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006176
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006177 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006178 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006179 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08006180 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006181 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006182
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006183 // Pilfer pointers from the monitor.
6184 // This should not do anything and the window should continue to receive events.
6185 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00006186
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006187 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006188 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006189 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006190 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006191
6192 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6193 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006194}
6195
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006196TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07006197 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006198 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6199 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006200 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07006201 window->setWindowOffset(20, 40);
6202 window->setWindowTransform(0, 1, -1, 0);
6203
Prabir Pradhanfb549072023-10-05 19:17:36 +00006204 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07006205
6206 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006207 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07006208 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6209 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006210 std::unique_ptr<MotionEvent> event = monitor.consumeMotion();
6211 ASSERT_NE(nullptr, event);
Evan Rosky84f07f02021-04-16 10:42:42 -07006212 // Even though window has transform, gesture monitor must not.
6213 ASSERT_EQ(ui::Transform(), event->getTransform());
6214}
6215
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006216TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00006217 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00006218 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00006219
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006220 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006221 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006222 << "Injection should fail if there is a monitor, but no touchable window";
6223 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00006224}
6225
Linnan Lid8150952024-01-26 18:07:17 +00006226/**
6227 * Two displays
6228 * The first monitor has a foreground window, a monitor
6229 * The second window has only one monitor.
6230 * We first inject a Down event into the first display, this injection should succeed and both
6231 * the foreground window and monitor should receive a down event, then inject a Down event into
6232 * the second display as well, this injection should fail, at this point, the first display
6233 * window and monitor should not receive a cancel or any other event.
6234 * Continue to inject Move and UP events to the first display, the events should be received
6235 * normally by the foreground window and monitor.
6236 */
6237TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCanceledWhenAnotherEmptyDisplayReceiveEvents) {
6238 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6239 sp<FakeWindowHandle> window =
6240 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6241
6242 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6243 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
6244
6245 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6246 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6247 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6248 {100, 200}))
6249 << "The down event injected into the first display should succeed";
6250
6251 window->consumeMotionDown();
6252 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006253
6254 ASSERT_EQ(InputEventInjectionResult::FAILED,
6255 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6256 {100, 200}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006257 << "The down event injected into the second display should fail since there's no "
6258 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006259
6260 // Continue to inject event to first display.
6261 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6262 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6263 ADISPLAY_ID_DEFAULT, {110, 220}))
6264 << "The move event injected into the first display should succeed";
6265
6266 window->consumeMotionMove();
6267 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006268
6269 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6270 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6271 {110, 220}))
6272 << "The up event injected into the first display should succeed";
6273
6274 window->consumeMotionUp();
6275 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006276
6277 window->assertNoEvents();
6278 monitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00006279 secondMonitor.assertNoEvents();
6280}
6281
6282/**
6283 * Two displays
6284 * There is a monitor and foreground window on each display.
6285 * First, we inject down events into each of the two displays, at this point, the foreground windows
6286 * and monitors on both displays should receive down events.
6287 * At this point, the foreground window of the second display goes away, the gone window should
6288 * receive the cancel event, and the other windows and monitors should not receive any events.
6289 * Inject a move event into the second display. At this point, the injection should fail because
6290 * the second display no longer has a foreground window. At this point, the monitor on the second
6291 * display should receive a cancel event, and any windows or monitors on the first display should
6292 * not receive any events, and any subsequent injection of events into the second display should
6293 * also fail.
6294 * Continue to inject events into the first display, and the events should all be injected
6295 * successfully and received normally.
6296 */
6297TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCancelWhenAnotherDisplayMonitorTouchCanceled) {
6298 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6299 sp<FakeWindowHandle> window =
6300 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6301 sp<FakeWindowHandle> secondWindow =
6302 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondForeground",
6303 SECOND_DISPLAY_ID);
6304
6305 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6306 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
6307
6308 // There is a foreground window on both displays.
6309 mDispatcher->onWindowInfosChanged({{*window->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
6310 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6311 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6312 {100, 200}))
6313 << "The down event injected into the first display should succeed";
6314
6315 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6316 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006317
6318 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6319 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6320 {100, 200}))
6321 << "The down event injected into the second display should succeed";
6322
Linnan Lid8150952024-01-26 18:07:17 +00006323 secondWindow->consumeMotionDown(SECOND_DISPLAY_ID);
6324 secondMonitor.consumeMotionDown(SECOND_DISPLAY_ID);
6325
6326 // Now second window is gone away.
6327 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6328
6329 // The gone window should receive a cancel, and the monitor on the second display should not
6330 // receive any events.
Linnan Lid8150952024-01-26 18:07:17 +00006331 secondWindow->consumeMotionCancel(SECOND_DISPLAY_ID);
6332 secondMonitor.assertNoEvents();
6333
6334 ASSERT_EQ(InputEventInjectionResult::FAILED,
6335 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6336 SECOND_DISPLAY_ID, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006337 << "The move event injected into the second display should fail because there's no "
6338 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006339 // Now the monitor on the second display should receive a cancel event.
6340 secondMonitor.consumeMotionCancel(SECOND_DISPLAY_ID);
Linnan Lid8150952024-01-26 18:07:17 +00006341
6342 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6343 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6344 ADISPLAY_ID_DEFAULT, {110, 200}))
6345 << "The move event injected into the first display should succeed";
6346
6347 window->consumeMotionMove();
6348 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006349
6350 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006351 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6352 {110, 220}))
6353 << "The up event injected into the second display should fail because there's no "
6354 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006355
6356 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6357 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6358 {110, 220}))
6359 << "The up event injected into the first display should succeed";
6360
6361 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6362 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006363
Linnan Lid8150952024-01-26 18:07:17 +00006364 window->assertNoEvents();
6365 monitor.assertNoEvents();
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006366 secondWindow->assertNoEvents();
6367 secondMonitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00006368}
6369
6370/**
6371 * One display with transform
6372 * There is a foreground window and a monitor on the display
6373 * Inject down event and move event sequentially, the foreground window and monitor can receive down
6374 * event and move event, then let the foreground window go away, the foreground window receives
6375 * cancel event, inject move event again, the monitor receives cancel event, all the events received
6376 * by the monitor should be with the same transform as the display
6377 */
6378TEST_F(InputDispatcherMonitorTest, MonitorTouchCancelEventWithDisplayTransform) {
6379 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6380 sp<FakeWindowHandle> window =
6381 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6382 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6383
6384 ui::Transform transform;
6385 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6386
6387 gui::DisplayInfo displayInfo;
6388 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6389 displayInfo.transform = transform;
6390
6391 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
6392
6393 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6394 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6395 {100, 200}))
6396 << "The down event injected should succeed";
6397
6398 window->consumeMotionDown();
6399 std::unique_ptr<MotionEvent> downMotionEvent = monitor.consumeMotion();
6400 EXPECT_EQ(transform, downMotionEvent->getTransform());
6401 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, downMotionEvent->getAction());
6402
6403 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6404 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6405 ADISPLAY_ID_DEFAULT, {110, 220}))
6406 << "The move event injected should succeed";
6407
6408 window->consumeMotionMove();
6409 std::unique_ptr<MotionEvent> moveMotionEvent = monitor.consumeMotion();
6410 EXPECT_EQ(transform, moveMotionEvent->getTransform());
6411 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, moveMotionEvent->getAction());
6412
6413 // Let foreground window gone
6414 mDispatcher->onWindowInfosChanged({{}, {displayInfo}, 0, 0});
6415
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006416 // Foreground window should receive a cancel event, but not the monitor.
Linnan Lid8150952024-01-26 18:07:17 +00006417 window->consumeMotionCancel();
Linnan Lid8150952024-01-26 18:07:17 +00006418
6419 ASSERT_EQ(InputEventInjectionResult::FAILED,
6420 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6421 ADISPLAY_ID_DEFAULT, {110, 220}))
6422 << "The move event injected should failed";
6423 // Now foreground should not receive any events, but monitor should receive a cancel event
6424 // with transform that same as display's display.
Linnan Lid8150952024-01-26 18:07:17 +00006425 std::unique_ptr<MotionEvent> cancelMotionEvent = monitor.consumeMotion();
6426 EXPECT_EQ(transform, cancelMotionEvent->getTransform());
6427 EXPECT_EQ(ADISPLAY_ID_DEFAULT, cancelMotionEvent->getDisplayId());
6428 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, cancelMotionEvent->getAction());
6429
6430 // Other event inject to this display should fail.
6431 ASSERT_EQ(InputEventInjectionResult::FAILED,
6432 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6433 ADISPLAY_ID_DEFAULT, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006434 << "The up event injected should fail because the touched window was removed";
Linnan Lid8150952024-01-26 18:07:17 +00006435 window->assertNoEvents();
6436 monitor.assertNoEvents();
6437}
6438
chaviw81e2bb92019-12-18 15:03:51 -08006439TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006440 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006441 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6442 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08006443
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006444 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08006445
6446 NotifyMotionArgs motionArgs =
6447 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6448 ADISPLAY_ID_DEFAULT);
6449
Prabir Pradhan678438e2023-04-13 19:32:51 +00006450 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08006451 // Window should receive motion down event.
6452 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6453
6454 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08006455 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08006456 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6457 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
6458 motionArgs.pointerCoords[0].getX() - 10);
6459
Prabir Pradhan678438e2023-04-13 19:32:51 +00006460 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006461 window->consumeMotionMove(ADISPLAY_ID_DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08006462}
6463
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006464/**
6465 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
6466 * the device default right away. In the test scenario, we check both the default value,
6467 * and the action of enabling / disabling.
6468 */
6469TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07006470 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006471 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6472 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08006473 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006474
6475 // Set focused application.
6476 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006477 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006478
6479 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006480 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006481 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006482 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006483
6484 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006485 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006486 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006487 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006488
6489 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006490 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006491 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006492 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07006493 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006494 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006495 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006496 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006497
6498 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006499 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006500 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006501 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006502
6503 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006504 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006505 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006506 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07006507 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006508 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006509 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006510 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006511
6512 window->assertNoEvents();
6513}
6514
Gang Wange9087892020-01-07 12:17:14 -05006515TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006516 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006517 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6518 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05006519
6520 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006521 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05006522
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006523 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006524 setFocusedWindow(window);
6525
Harry Cutts33476232023-01-30 19:57:29 +00006526 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05006527
Prabir Pradhan678438e2023-04-13 19:32:51 +00006528 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
6529 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05006530
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006531 std::unique_ptr<KeyEvent> event = window->consumeKey();
6532 ASSERT_NE(event, nullptr);
6533 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Gang Wange9087892020-01-07 12:17:14 -05006534 ASSERT_NE(verified, nullptr);
6535 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
6536
6537 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
6538 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
6539 ASSERT_EQ(keyArgs.source, verified->source);
6540 ASSERT_EQ(keyArgs.displayId, verified->displayId);
6541
6542 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
6543
6544 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05006545 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006546 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05006547 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
6548 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
6549 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
6550 ASSERT_EQ(0, verifiedKey.repeatCount);
6551}
6552
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006553TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006554 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006555 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6556 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006557
6558 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6559
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006560 ui::Transform transform;
6561 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6562
6563 gui::DisplayInfo displayInfo;
6564 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6565 displayInfo.transform = transform;
6566
Patrick Williamsd828f302023-04-28 17:52:08 -05006567 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006568
Prabir Pradhan678438e2023-04-13 19:32:51 +00006569 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006570 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6571 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006572 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006573
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006574 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
6575 ASSERT_NE(nullptr, event);
6576 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006577 ASSERT_NE(verified, nullptr);
6578 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
6579
6580 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
6581 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
6582 EXPECT_EQ(motionArgs.source, verified->source);
6583 EXPECT_EQ(motionArgs.displayId, verified->displayId);
6584
6585 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
6586
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006587 const vec2 rawXY =
6588 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
6589 motionArgs.pointerCoords[0].getXYValue());
6590 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
6591 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006592 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006593 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006594 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006595 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
6596 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
6597}
6598
chaviw09c8d2d2020-08-24 15:48:26 -07006599/**
6600 * Ensure that separate calls to sign the same data are generating the same key.
6601 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
6602 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
6603 * tests.
6604 */
6605TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
6606 KeyEvent event = getTestKeyEvent();
6607 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6608
6609 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
6610 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
6611 ASSERT_EQ(hmac1, hmac2);
6612}
6613
6614/**
6615 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6616 */
6617TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6618 KeyEvent event = getTestKeyEvent();
6619 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6620 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6621
6622 verifiedEvent.deviceId += 1;
6623 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6624
6625 verifiedEvent.source += 1;
6626 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6627
6628 verifiedEvent.eventTimeNanos += 1;
6629 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6630
6631 verifiedEvent.displayId += 1;
6632 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6633
6634 verifiedEvent.action += 1;
6635 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6636
6637 verifiedEvent.downTimeNanos += 1;
6638 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6639
6640 verifiedEvent.flags += 1;
6641 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6642
6643 verifiedEvent.keyCode += 1;
6644 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6645
6646 verifiedEvent.scanCode += 1;
6647 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6648
6649 verifiedEvent.metaState += 1;
6650 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6651
6652 verifiedEvent.repeatCount += 1;
6653 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6654}
6655
Vishnu Nair958da932020-08-21 17:12:37 -07006656TEST_F(InputDispatcherTest, SetFocusedWindow) {
6657 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6658 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006659 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006660 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006661 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006662 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6663
6664 // Top window is also focusable but is not granted focus.
6665 windowTop->setFocusable(true);
6666 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006667 mDispatcher->onWindowInfosChanged(
6668 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006669 setFocusedWindow(windowSecond);
6670
6671 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006672 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006673 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006674
6675 // Focused window should receive event.
6676 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6677 windowTop->assertNoEvents();
6678}
6679
6680TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
6681 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6682 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006683 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006684 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6685
6686 window->setFocusable(true);
6687 // Release channel for window is no longer valid.
6688 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006689 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006690 setFocusedWindow(window);
6691
6692 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006693 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006694
6695 // window channel is invalid, so it should not receive any input event.
6696 window->assertNoEvents();
6697}
6698
6699TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
6700 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6701 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006702 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006703 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006704 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6705
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006706 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006707 setFocusedWindow(window);
6708
6709 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006710 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006711
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006712 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006713 window->assertNoEvents();
6714}
6715
6716TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6717 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6718 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006719 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006720 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006721 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006722 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6723
6724 windowTop->setFocusable(true);
6725 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006726 mDispatcher->onWindowInfosChanged(
6727 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006728 setFocusedWindow(windowTop);
6729 windowTop->consumeFocusEvent(true);
6730
Chavi Weingarten847e8512023-03-29 00:26:09 +00006731 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006732 mDispatcher->onWindowInfosChanged(
6733 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006734 windowSecond->consumeFocusEvent(true);
6735 windowTop->consumeFocusEvent(false);
6736
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006737 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006738 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006739
6740 // Focused window should receive event.
6741 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6742}
6743
Chavi Weingarten847e8512023-03-29 00:26:09 +00006744TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006745 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6746 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006747 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006748 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006749 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006750 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6751
6752 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006753 windowSecond->setFocusable(false);
6754 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006755 mDispatcher->onWindowInfosChanged(
6756 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006757 setFocusedWindow(windowTop);
6758 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006759
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006760 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006761 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006762
6763 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006764 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006765 windowSecond->assertNoEvents();
6766}
6767
6768TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6769 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6770 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006771 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006772 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006773 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6774 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006775 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6776
6777 window->setFocusable(true);
6778 previousFocusedWindow->setFocusable(true);
6779 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006780 mDispatcher->onWindowInfosChanged(
6781 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006782 setFocusedWindow(previousFocusedWindow);
6783 previousFocusedWindow->consumeFocusEvent(true);
6784
6785 // Requesting focus on invisible window takes focus from currently focused window.
6786 setFocusedWindow(window);
6787 previousFocusedWindow->consumeFocusEvent(false);
6788
6789 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006790 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006791 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6792 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006793
6794 // Window does not get focus event or key down.
6795 window->assertNoEvents();
6796
6797 // Window becomes visible.
6798 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006799 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006800
6801 // Window receives focus event.
6802 window->consumeFocusEvent(true);
6803 // Focused window receives key down.
6804 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6805}
6806
Vishnu Nair599f1412021-06-21 10:39:58 -07006807TEST_F(InputDispatcherTest, DisplayRemoved) {
6808 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6809 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006810 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006811 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6812
6813 // window is granted focus.
6814 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006815 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006816 setFocusedWindow(window);
6817 window->consumeFocusEvent(true);
6818
6819 // When a display is removed window loses focus.
6820 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6821 window->consumeFocusEvent(false);
6822}
6823
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006824/**
6825 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6826 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6827 * of the 'slipperyEnterWindow'.
6828 *
6829 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6830 * a way so that the touched location is no longer covered by the top window.
6831 *
6832 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6833 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6834 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6835 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6836 * with ACTION_DOWN).
6837 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6838 * window moved itself away from the touched location and had Flag::SLIPPERY.
6839 *
6840 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6841 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6842 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6843 *
6844 * In this test, we ensure that the event received by the bottom window has
6845 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6846 */
6847TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006848 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006849 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006850
6851 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6852 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6853
6854 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006855 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006856 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006857 // Make sure this one overlaps the bottom window
6858 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6859 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6860 // one. Windows with the same owner are not considered to be occluding each other.
6861 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6862
6863 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006864 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006865 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6866
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006867 mDispatcher->onWindowInfosChanged(
6868 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006869
6870 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006871 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6872 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6873 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006874 slipperyExitWindow->consumeMotionDown();
6875 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006876 mDispatcher->onWindowInfosChanged(
6877 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006878
Prabir Pradhan678438e2023-04-13 19:32:51 +00006879 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6880 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6881 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006882
6883 slipperyExitWindow->consumeMotionCancel();
6884
6885 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6886 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6887}
6888
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006889/**
6890 * Two windows, one on the left and another on the right. The left window is slippery. The right
6891 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6892 * touch moves from the left window into the right window, the gesture should continue to go to the
6893 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6894 * reproduces a crash.
6895 */
6896TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6897 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6898
6899 sp<FakeWindowHandle> leftSlipperyWindow =
6900 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6901 leftSlipperyWindow->setSlippery(true);
6902 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6903
6904 sp<FakeWindowHandle> rightDropTouchesWindow =
6905 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6906 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6907 rightDropTouchesWindow->setDropInput(true);
6908
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006909 mDispatcher->onWindowInfosChanged(
6910 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006911
6912 // Start touch in the left window
6913 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6914 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6915 .build());
6916 leftSlipperyWindow->consumeMotionDown();
6917
6918 // And move it into the right window
6919 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6920 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6921 .build());
6922
6923 // Since the right window isn't eligible to receive input, touch does not slip.
6924 // The left window continues to receive the gesture.
6925 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6926 rightDropTouchesWindow->assertNoEvents();
6927}
6928
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006929/**
6930 * A single window is on screen first. Touch is injected into that window. Next, a second window
6931 * appears. Since the first window is slippery, touch will move from the first window to the second.
6932 */
6933TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6934 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6935 sp<FakeWindowHandle> originalWindow =
6936 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6937 originalWindow->setFrame(Rect(0, 0, 200, 200));
6938 originalWindow->setSlippery(true);
6939
6940 sp<FakeWindowHandle> appearingWindow =
6941 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6942 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6943
6944 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6945
6946 // Touch down on the original window
6947 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6948 injectMotionEvent(*mDispatcher,
6949 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6950 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6951 .build()));
6952 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6953
6954 // Now, a new window appears. This could be, for example, a notification shade that appears
6955 // after user starts to drag down on the launcher window.
6956 mDispatcher->onWindowInfosChanged(
6957 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6958 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6959 injectMotionEvent(*mDispatcher,
6960 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6961 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6962 .build()));
6963 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6964 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6965 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6966 injectMotionEvent(*mDispatcher,
6967 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6968 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6969 .build()));
6970 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6971
6972 originalWindow->assertNoEvents();
6973 appearingWindow->assertNoEvents();
6974}
6975
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006976TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006977 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006978 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6979
6980 sp<FakeWindowHandle> leftWindow =
6981 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6982 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006983 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006984
6985 sp<FakeWindowHandle> rightSpy =
6986 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6987 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006988 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006989 rightSpy->setSpy(true);
6990 rightSpy->setTrustedOverlay(true);
6991
6992 sp<FakeWindowHandle> rightWindow =
6993 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6994 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006995 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006996
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006997 mDispatcher->onWindowInfosChanged(
6998 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006999
7000 // Touch in the left window
7001 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7002 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7003 .build());
7004 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
7005 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007006 ASSERT_NO_FATAL_FAILURE(
7007 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007008
7009 // Touch another finger over the right windows
7010 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7011 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7012 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7013 .build());
7014 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
7015 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
7016 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
7017 mDispatcher->waitForIdle();
7018 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007019 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
7020 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007021
7022 // Release finger over left window. The UP actions are not treated as device interaction.
7023 // The windows that did not receive the UP pointer will receive MOVE events, but since this
7024 // is part of the UP action, we do not treat this as device interaction.
7025 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
7026 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7027 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7028 .build());
7029 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
7030 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
7031 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
7032 mDispatcher->waitForIdle();
7033 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7034
7035 // Move remaining finger
7036 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7037 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7038 .build());
7039 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
7040 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
7041 mDispatcher->waitForIdle();
7042 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007043 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007044
7045 // Release all fingers
7046 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7047 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7048 .build());
7049 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
7050 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
7051 mDispatcher->waitForIdle();
7052 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7053}
7054
7055TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
7056 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7057
7058 sp<FakeWindowHandle> window =
7059 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
7060 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007061 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007062
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007063 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007064 setFocusedWindow(window);
7065 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
7066
7067 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
7068 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
7069 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007070 ASSERT_NO_FATAL_FAILURE(
7071 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007072
7073 // The UP actions are not treated as device interaction.
7074 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
7075 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
7076 mDispatcher->waitForIdle();
7077 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7078}
7079
Prabir Pradhan5893d362023-11-17 04:30:40 +00007080TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
7081 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7082
7083 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
7084 ADISPLAY_ID_DEFAULT);
7085 left->setFrame(Rect(0, 0, 100, 100));
7086 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
7087 "Right Window", ADISPLAY_ID_DEFAULT);
7088 right->setFrame(Rect(100, 0, 200, 100));
7089 sp<FakeWindowHandle> spy =
7090 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
7091 spy->setFrame(Rect(0, 0, 200, 100));
7092 spy->setTrustedOverlay(true);
7093 spy->setSpy(true);
7094
7095 mDispatcher->onWindowInfosChanged(
7096 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
7097
7098 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
7099 NotifyMotionArgs notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
7100 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
7101 mDispatcher->notifyMotion(notifyArgs);
7102
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007103 std::unique_ptr<MotionEvent> leftEnter = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00007104 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
7105 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007106 ASSERT_NE(nullptr, leftEnter);
Prabir Pradhan5893d362023-11-17 04:30:40 +00007107 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
7108 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007109 Not(WithEventId(leftEnter->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00007110 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
7111
7112 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
7113 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
7114 {PointF{150, 50}});
7115 mDispatcher->notifyMotion(notifyArgs);
7116
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007117 std::unique_ptr<MotionEvent> leftExit = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00007118 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
7119 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007120 ASSERT_NE(nullptr, leftExit);
Prabir Pradhan5893d362023-11-17 04:30:40 +00007121 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
7122 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007123 Not(WithEventId(leftExit->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00007124 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
7125
7126 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
7127}
7128
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00007129class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
7130protected:
7131 std::shared_ptr<FakeApplicationHandle> mApp;
7132 sp<FakeWindowHandle> mWindow;
7133
7134 virtual void SetUp() override {
7135 InputDispatcherTest::SetUp();
7136
7137 mApp = std::make_shared<FakeApplicationHandle>();
7138
7139 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
7140 mWindow->setFrame(Rect(0, 0, 100, 100));
7141
7142 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
7143 setFocusedWindow(mWindow);
7144 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
7145 }
7146
7147 void setFallback(int32_t keycode) {
7148 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
7149 return KeyEventBuilder(event).keyCode(keycode).build();
7150 });
7151 }
7152
7153 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007154 std::unique_ptr<KeyEvent> event = mWindow->consumeKey(handled);
7155 ASSERT_NE(nullptr, event);
7156 ASSERT_THAT(*event, matcher);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00007157 }
7158};
7159
7160TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
7161 mDispatcher->notifyKey(
7162 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7163 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
7164 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7165}
7166
7167TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
7168 mDispatcher->notifyKey(
7169 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7170 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
7171 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7172}
7173
7174TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
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
7183 // Since the policy did not request any fallback to be generated, ensure there are no events.
7184 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7185}
7186
7187TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
7188 setFallback(AKEYCODE_B);
7189 mDispatcher->notifyKey(
7190 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7191
7192 // Do not handle this key event.
7193 consumeKey(/*handled=*/false,
7194 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7195
7196 // Since the key was not handled, ensure the fallback event was dispatched instead.
7197 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7198 consumeKey(/*handled=*/true,
7199 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7200 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7201
7202 // Release the original key, and ensure the fallback key is also released.
7203 mDispatcher->notifyKey(
7204 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7205 consumeKey(/*handled=*/false,
7206 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7207 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7208 consumeKey(/*handled=*/true,
7209 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7210 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7211
7212 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7213 mWindow->assertNoEvents();
7214}
7215
7216TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
7217 setFallback(AKEYCODE_B);
7218 mDispatcher->notifyKey(
7219 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7220
7221 // Do not handle this key event, but handle the fallback.
7222 consumeKey(/*handled=*/false,
7223 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7224 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7225 consumeKey(/*handled=*/true,
7226 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7227 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7228
7229 // Release the original key, and ensure the fallback key is also released.
7230 mDispatcher->notifyKey(
7231 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7232 // But this time, the app handles the original key.
7233 consumeKey(/*handled=*/true,
7234 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7235 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7236 // Ensure the fallback key is canceled.
7237 consumeKey(/*handled=*/true,
7238 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7239 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7240
7241 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7242 mWindow->assertNoEvents();
7243}
7244
7245TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
7246 setFallback(AKEYCODE_B);
7247 mDispatcher->notifyKey(
7248 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7249
7250 // Do not handle this key event.
7251 consumeKey(/*handled=*/false,
7252 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7253 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7254 // App does not handle the fallback either, so ensure another fallback is not generated.
7255 setFallback(AKEYCODE_C);
7256 consumeKey(/*handled=*/false,
7257 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7258 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7259
7260 // Release the original key, and ensure the fallback key is also released.
7261 setFallback(AKEYCODE_B);
7262 mDispatcher->notifyKey(
7263 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7264 consumeKey(/*handled=*/false,
7265 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7266 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7267 consumeKey(/*handled=*/false,
7268 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7269 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7270
7271 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7272 mWindow->assertNoEvents();
7273}
7274
7275TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
7276 setFallback(AKEYCODE_B);
7277 mDispatcher->notifyKey(
7278 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7279
7280 // Do not handle this key event, so fallback is generated.
7281 consumeKey(/*handled=*/false,
7282 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7283 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7284 consumeKey(/*handled=*/true,
7285 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7286 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7287
7288 // Release the original key, but assume the policy is misbehaving and it
7289 // generates an inconsistent fallback to the one from the DOWN event.
7290 setFallback(AKEYCODE_C);
7291 mDispatcher->notifyKey(
7292 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7293 consumeKey(/*handled=*/false,
7294 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7295 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7296 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
7297 consumeKey(/*handled=*/true,
7298 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7299 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7300
7301 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7302 mWindow->assertNoEvents();
7303}
7304
7305TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
7306 setFallback(AKEYCODE_B);
7307 mDispatcher->notifyKey(
7308 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7309
7310 // Do not handle this key event, so fallback is generated.
7311 consumeKey(/*handled=*/false,
7312 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7313 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7314 consumeKey(/*handled=*/true,
7315 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7316 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7317
7318 // The original key is canceled.
7319 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
7320 .keyCode(AKEYCODE_A)
7321 .addFlag(AKEY_EVENT_FLAG_CANCELED)
7322 .build());
7323 consumeKey(/*handled=*/false,
7324 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
7325 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7326 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7327 // Ensure the fallback key is also canceled due to the original key being canceled.
7328 consumeKey(/*handled=*/true,
7329 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7330 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7331
7332 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7333 mWindow->assertNoEvents();
7334}
7335
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00007336TEST_F(InputDispatcherFallbackKeyTest, InputChannelRemovedDuringPolicyCall) {
Prabir Pradhanb13da8f2024-01-09 23:10:13 +00007337 setFallback(AKEYCODE_B);
7338 mDispatcher->notifyKey(
7339 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7340
7341 // Do not handle this key event.
7342 consumeKey(/*handled=*/false,
7343 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7344 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7345 consumeKey(/*handled=*/true,
7346 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7347 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7348
7349 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
7350 // When the unhandled key is reported to the policy next, remove the input channel.
7351 mDispatcher->removeInputChannel(mWindow->getToken());
7352 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
7353 });
7354 // Release the original key, and let the app now handle the previously unhandled key.
7355 // This should result in the previously generated fallback key to be cancelled.
7356 // Since the policy was notified of the unhandled DOWN event earlier, it will also be notified
7357 // of the UP event for consistency. The Dispatcher calls into the policy from its own thread
7358 // without holding the lock, because it need to synchronously fetch the fallback key. While in
7359 // the policy call, we will now remove the input channel. Once the policy call returns, the
7360 // Dispatcher will no longer have a channel to send cancellation events to. Ensure this does
7361 // not cause any crashes.
7362 mDispatcher->notifyKey(
7363 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7364 consumeKey(/*handled=*/true,
7365 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7366 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7367}
7368
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00007369TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedDuringPolicyCall) {
7370 setFallback(AKEYCODE_B);
7371 mDispatcher->notifyKey(
7372 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7373
7374 // Do not handle this key event.
7375 consumeKey(/*handled=*/false,
7376 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7377 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7378 consumeKey(/*handled=*/true,
7379 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7380 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7381
7382 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
7383 // When the unhandled key is reported to the policy next, remove the window.
7384 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
7385 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
7386 });
7387 // Release the original key, which the app will not handle. When this unhandled key is reported
7388 // to the policy, the window will be removed.
7389 mDispatcher->notifyKey(
7390 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7391 consumeKey(/*handled=*/false,
7392 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7393 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7394
7395 // Since the window was removed, it loses focus, and the channel state will be reset.
7396 consumeKey(/*handled=*/true,
7397 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7398 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7399 mWindow->consumeFocusEvent(false);
7400 mWindow->assertNoEvents();
7401}
7402
7403TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedWhileAwaitingFinishedSignal) {
7404 setFallback(AKEYCODE_B);
7405 mDispatcher->notifyKey(
7406 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7407
7408 // Do not handle this key event.
7409 consumeKey(/*handled=*/false,
7410 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7411 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7412 const auto [seq, event] = mWindow->receiveEvent();
7413 ASSERT_TRUE(seq.has_value() && event != nullptr) << "Failed to receive fallback event";
7414 ASSERT_EQ(event->getType(), InputEventType::KEY);
7415 ASSERT_THAT(static_cast<const KeyEvent&>(*event),
7416 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7417 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7418
7419 // Remove the window now, which should generate a cancellations and make the window lose focus.
7420 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
7421 consumeKey(/*handled=*/true,
7422 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
7423 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7424 consumeKey(/*handled=*/true,
7425 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7426 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7427 mWindow->consumeFocusEvent(false);
7428
7429 // Finish the event by reporting it as handled.
7430 mWindow->finishEvent(*seq);
7431 mWindow->assertNoEvents();
7432}
7433
Garfield Tan1c7bc862020-01-28 13:24:04 -08007434class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
7435protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08007436 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
7437 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007438
Chris Yea209fde2020-07-22 13:54:51 -07007439 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007440 sp<FakeWindowHandle> mWindow;
7441
7442 virtual void SetUp() override {
Prabir Pradhandae52792023-12-15 07:36:40 +00007443 InputDispatcherTest::SetUp();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007444
Prabir Pradhandae52792023-12-15 07:36:40 +00007445 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007446 setUpWindow();
7447 }
7448
7449 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07007450 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007451 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007452
Vishnu Nair47074b82020-08-14 11:54:47 -07007453 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007454 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007455 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007456 mWindow->consumeFocusEvent(true);
7457 }
7458
Chris Ye2ad95392020-09-01 13:44:44 -07007459 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007460 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007461 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007462 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007463 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007464
7465 // Window should receive key down event.
7466 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7467 }
7468
7469 void expectKeyRepeatOnce(int32_t repeatCount) {
7470 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007471 mWindow->consumeKeyEvent(
7472 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007473 }
7474
Chris Ye2ad95392020-09-01 13:44:44 -07007475 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007476 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007477 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007478 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007479 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007480
7481 // Window should receive key down event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007482 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007483 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007484 }
Hu Guofe3c8f12023-09-22 17:20:15 +08007485
7486 void injectKeyRepeat(int32_t repeatCount) {
7487 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7488 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, repeatCount, ADISPLAY_ID_DEFAULT))
7489 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
7490 }
Garfield Tan1c7bc862020-01-28 13:24:04 -08007491};
7492
7493TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00007494 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007495 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7496 expectKeyRepeatOnce(repeatCount);
7497 }
7498}
7499
7500TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00007501 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007502 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7503 expectKeyRepeatOnce(repeatCount);
7504 }
Harry Cutts33476232023-01-30 19:57:29 +00007505 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007506 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08007507 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7508 expectKeyRepeatOnce(repeatCount);
7509 }
7510}
7511
7512TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007513 sendAndConsumeKeyDown(/*deviceId=*/1);
7514 expectKeyRepeatOnce(/*repeatCount=*/1);
7515 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007516 mWindow->assertNoEvents();
7517}
7518
7519TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007520 sendAndConsumeKeyDown(/*deviceId=*/1);
7521 expectKeyRepeatOnce(/*repeatCount=*/1);
7522 sendAndConsumeKeyDown(/*deviceId=*/2);
7523 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007524 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00007525 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007526 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00007527 expectKeyRepeatOnce(/*repeatCount=*/2);
7528 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07007529 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00007530 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007531 mWindow->assertNoEvents();
7532}
7533
7534TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007535 sendAndConsumeKeyDown(/*deviceId=*/1);
7536 expectKeyRepeatOnce(/*repeatCount=*/1);
7537 sendAndConsumeKeyDown(/*deviceId=*/2);
7538 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007539 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00007540 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007541 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08007542 mWindow->assertNoEvents();
7543}
7544
liushenxiang42232912021-05-21 20:24:09 +08007545TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
7546 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00007547 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007548 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08007549 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
7550 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
7551 mWindow->assertNoEvents();
7552}
7553
Garfield Tan1c7bc862020-01-28 13:24:04 -08007554TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007555 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007556 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007557 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007558 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
7559 ASSERT_NE(nullptr, repeatEvent);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007560 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007561 IdGenerator::getSource(repeatEvent->getId()));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007562 }
7563}
7564
7565TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007566 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007567 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007568
7569 std::unordered_set<int32_t> idSet;
7570 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007571 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
7572 ASSERT_NE(nullptr, repeatEvent);
7573 int32_t id = repeatEvent->getId();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007574 EXPECT_EQ(idSet.end(), idSet.find(id));
7575 idSet.insert(id);
7576 }
7577}
7578
Hu Guofe3c8f12023-09-22 17:20:15 +08007579TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_CorrectRepeatCountWhenInjectKeyRepeat) {
7580 injectKeyRepeat(0);
7581 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7582 for (int32_t repeatCount = 1; repeatCount <= 2; ++repeatCount) {
7583 expectKeyRepeatOnce(repeatCount);
7584 }
7585 injectKeyRepeat(1);
7586 // Expect repeatCount to be 3 instead of 1
7587 expectKeyRepeatOnce(3);
7588}
7589
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007590/* Test InputDispatcher for MultiDisplay */
7591class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
7592public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007593 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007594 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08007595
Chris Yea209fde2020-07-22 13:54:51 -07007596 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007597 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007598 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007599
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007600 // Set focus window for primary display, but focused display would be second one.
7601 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07007602 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007603 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
7604
Vishnu Nair958da932020-08-21 17:12:37 -07007605 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007606 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08007607
Chris Yea209fde2020-07-22 13:54:51 -07007608 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007609 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007610 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007611 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007612 // Set focus display to second one.
7613 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
7614 // Set focus window for second display.
7615 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07007616 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007617 mDispatcher->onWindowInfosChanged(
7618 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007619 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007620 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007621 }
7622
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007623 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007624 InputDispatcherTest::TearDown();
7625
Chris Yea209fde2020-07-22 13:54:51 -07007626 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007627 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07007628 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007629 windowInSecondary.clear();
7630 }
7631
7632protected:
Chris Yea209fde2020-07-22 13:54:51 -07007633 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007634 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07007635 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007636 sp<FakeWindowHandle> windowInSecondary;
7637};
7638
7639TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
7640 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007642 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007643 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007644 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08007645 windowInSecondary->assertNoEvents();
7646
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007647 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007648 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007649 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007650 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007651 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007652 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08007653}
7654
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007655TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08007656 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007657 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007658 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007659 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007660 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08007661 windowInSecondary->assertNoEvents();
7662
7663 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007664 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007665 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007666 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007667 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08007668
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007669 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007670 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08007671
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007672 // Old focus should receive a cancel event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007673 windowInSecondary->consumeKeyUp(ADISPLAY_ID_NONE, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08007674
7675 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007676 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08007677 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007678 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08007679 windowInSecondary->assertNoEvents();
7680}
7681
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007682// Test per-display input monitors for motion event.
7683TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08007684 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007685 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007686 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007687 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007688
7689 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007690 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007691 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007692 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007693 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007694 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007695 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007696 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007697
7698 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007699 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007700 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007701 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007702 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007703 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007704 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08007705 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007706
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007707 // Lift up the touch from the second display
7708 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007709 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007710 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7711 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
7712 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
7713
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007714 // Test inject a non-pointer motion event.
7715 // If specific a display, it will dispatch to the focused window of particular display,
7716 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007717 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007718 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007719 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007720 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007721 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007722 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007723 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007724}
7725
7726// Test per-display input monitors for key event.
7727TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007728 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08007729 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007730 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007731 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007732 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007733
7734 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007735 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007736 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007737 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007738 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007739 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007740 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007741}
7742
Vishnu Nair958da932020-08-21 17:12:37 -07007743TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
7744 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007745 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007746 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007747 mDispatcher->onWindowInfosChanged(
7748 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
7749 *windowInSecondary->getInfo()},
7750 {},
7751 0,
7752 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007753 setFocusedWindow(secondWindowInPrimary);
7754 windowInPrimary->consumeFocusEvent(false);
7755 secondWindowInPrimary->consumeFocusEvent(true);
7756
7757 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007758 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7759 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007760 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007761 windowInPrimary->assertNoEvents();
7762 windowInSecondary->assertNoEvents();
7763 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7764}
7765
Arthur Hungdfd528e2021-12-08 13:23:04 +00007766TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
7767 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007768 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007769 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007770 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007771
7772 // Test touch down on primary display.
7773 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007774 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007775 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7776 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7777 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
7778
7779 // Test touch down on second display.
7780 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007781 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007782 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7783 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
7784 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
7785
7786 // Trigger cancel touch.
7787 mDispatcher->cancelCurrentTouch();
7788 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7789 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7790 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
7791 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
7792
7793 // Test inject a move motion event, no window/monitor should receive the event.
7794 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007795 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007796 ADISPLAY_ID_DEFAULT, {110, 200}))
7797 << "Inject motion event should return InputEventInjectionResult::FAILED";
7798 windowInPrimary->assertNoEvents();
7799 monitorInPrimary.assertNoEvents();
7800
7801 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007802 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007803 SECOND_DISPLAY_ID, {110, 200}))
7804 << "Inject motion event should return InputEventInjectionResult::FAILED";
7805 windowInSecondary->assertNoEvents();
7806 monitorInSecondary.assertNoEvents();
7807}
7808
Hu Guocb134f12023-12-23 13:42:44 +00007809/**
7810 * Send a key to the primary display and to the secondary display.
7811 * Then cause the key on the primary display to be canceled by sending in a stale key.
7812 * Ensure that the key on the primary display is canceled, and that the key on the secondary display
7813 * does not get canceled.
7814 */
7815TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture) {
7816 // Send a key down on primary display
7817 mDispatcher->notifyKey(
7818 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7819 .displayId(ADISPLAY_ID_DEFAULT)
7820 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7821 .build());
7822 windowInPrimary->consumeKeyEvent(
7823 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7824 windowInSecondary->assertNoEvents();
7825
7826 // Send a key down on second display
7827 mDispatcher->notifyKey(
7828 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7829 .displayId(SECOND_DISPLAY_ID)
7830 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7831 .build());
7832 windowInSecondary->consumeKeyEvent(
7833 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7834 windowInPrimary->assertNoEvents();
7835
7836 // Send a valid key up event on primary display that will be dropped because it is stale
7837 NotifyKeyArgs staleKeyUp =
7838 KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
7839 .displayId(ADISPLAY_ID_DEFAULT)
7840 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7841 .build();
7842 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7843 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7844 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7845 mDispatcher->notifyKey(staleKeyUp);
7846
7847 // Only the key gesture corresponding to the dropped event should receive the cancel event.
7848 // Therefore, windowInPrimary should get the cancel event and windowInSecondary should not
7849 // receive any events.
7850 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
7851 WithDisplayId(ADISPLAY_ID_DEFAULT),
7852 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7853 windowInSecondary->assertNoEvents();
7854}
7855
7856/**
7857 * Similar to 'WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture' but for motion events.
7858 */
7859TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropMotionEvent_OnlyCancelCorrespondingGesture) {
7860 // Send touch down on primary display.
7861 mDispatcher->notifyMotion(
7862 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7863 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7864 .displayId(ADISPLAY_ID_DEFAULT)
7865 .build());
7866 windowInPrimary->consumeMotionEvent(
7867 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7868 windowInSecondary->assertNoEvents();
7869
7870 // Send touch down on second display.
7871 mDispatcher->notifyMotion(
7872 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7873 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7874 .displayId(SECOND_DISPLAY_ID)
7875 .build());
7876 windowInPrimary->assertNoEvents();
7877 windowInSecondary->consumeMotionEvent(
7878 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7879
7880 // inject a valid MotionEvent on primary display that will be stale when it arrives.
7881 NotifyMotionArgs staleMotionUp =
7882 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7883 .displayId(ADISPLAY_ID_DEFAULT)
7884 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7885 .build();
7886 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7887 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7888 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7889 mDispatcher->notifyMotion(staleMotionUp);
7890
7891 // For stale motion events, we let the gesture to complete. This behaviour is different from key
7892 // events, where we would cancel the current keys instead.
7893 windowInPrimary->consumeMotionEvent(WithMotionAction(ACTION_UP));
7894 windowInSecondary->assertNoEvents();
7895}
7896
Jackal Guof9696682018-10-05 12:23:23 +08007897class InputFilterTest : public InputDispatcherTest {
7898protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007899 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
7900 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08007901 NotifyMotionArgs motionArgs;
7902
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007903 motionArgs =
7904 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007905 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007906 motionArgs =
7907 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007908 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007909 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007910 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007911 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007912 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08007913 } else {
7914 mFakePolicy->assertFilterInputEventWasNotCalled();
7915 }
7916 }
7917
7918 void testNotifyKey(bool expectToBeFiltered) {
7919 NotifyKeyArgs keyArgs;
7920
7921 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007922 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007923 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007924 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007925 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007926
7927 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08007928 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007929 } else {
7930 mFakePolicy->assertFilterInputEventWasNotCalled();
7931 }
7932 }
7933};
7934
7935// Test InputFilter for MotionEvent
7936TEST_F(InputFilterTest, MotionEvent_InputFilter) {
7937 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007938 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7939 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007940
7941 // Enable InputFilter
7942 mDispatcher->setInputFilterEnabled(true);
7943 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007944 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
7945 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007946
7947 // Disable InputFilter
7948 mDispatcher->setInputFilterEnabled(false);
7949 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007950 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7951 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007952}
7953
7954// Test InputFilter for KeyEvent
7955TEST_F(InputFilterTest, KeyEvent_InputFilter) {
7956 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007957 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007958
7959 // Enable InputFilter
7960 mDispatcher->setInputFilterEnabled(true);
7961 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007962 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007963
7964 // Disable InputFilter
7965 mDispatcher->setInputFilterEnabled(false);
7966 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007967 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007968}
7969
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007970// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
7971// logical display coordinate space.
7972TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
7973 ui::Transform firstDisplayTransform;
7974 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7975 ui::Transform secondDisplayTransform;
7976 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
7977
7978 std::vector<gui::DisplayInfo> displayInfos(2);
7979 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
7980 displayInfos[0].transform = firstDisplayTransform;
7981 displayInfos[1].displayId = SECOND_DISPLAY_ID;
7982 displayInfos[1].transform = secondDisplayTransform;
7983
Patrick Williamsd828f302023-04-28 17:52:08 -05007984 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007985
7986 // Enable InputFilter
7987 mDispatcher->setInputFilterEnabled(true);
7988
7989 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007990 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
7991 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007992}
7993
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007994class InputFilterInjectionPolicyTest : public InputDispatcherTest {
7995protected:
7996 virtual void SetUp() override {
7997 InputDispatcherTest::SetUp();
7998
7999 /**
8000 * We don't need to enable input filter to test the injected event policy, but we enabled it
8001 * here to make the tests more realistic, since this policy only matters when inputfilter is
8002 * on.
8003 */
8004 mDispatcher->setInputFilterEnabled(true);
8005
8006 std::shared_ptr<InputApplicationHandle> application =
8007 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008008 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
8009 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008010
8011 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8012 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008013 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008014 setFocusedWindow(mWindow);
8015 mWindow->consumeFocusEvent(true);
8016 }
8017
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008018 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
8019 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008020 KeyEvent event;
8021
8022 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
8023 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
8024 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00008025 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008026 const int32_t additionalPolicyFlags =
8027 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
8028 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00008029 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00008030 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008031 policyFlags | additionalPolicyFlags));
8032
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008033 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008034 }
8035
8036 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
8037 int32_t flags) {
8038 MotionEvent event;
8039 PointerProperties pointerProperties[1];
8040 PointerCoords pointerCoords[1];
8041 pointerProperties[0].clear();
8042 pointerProperties[0].id = 0;
8043 pointerCoords[0].clear();
8044 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
8045 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
8046
8047 ui::Transform identityTransform;
8048 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
8049 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
8050 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
8051 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
8052 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07008053 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07008054 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00008055 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008056
8057 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
8058 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00008059 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00008060 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008061 policyFlags | additionalPolicyFlags));
8062
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008063 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008064 }
8065
8066private:
8067 sp<FakeWindowHandle> mWindow;
8068};
8069
8070TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008071 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
8072 // filter. Without it, the event will no different from a regularly injected event, and the
8073 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00008074 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
8075 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008076}
8077
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008078TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008079 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00008080 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008081 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
8082}
8083
8084TEST_F(InputFilterInjectionPolicyTest,
8085 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
8086 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00008087 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008088 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008089}
8090
8091TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00008092 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
8093 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008094}
8095
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08008096class InputDispatcherUserActivityPokeTests : public InputDispatcherTest {
8097protected:
8098 virtual void SetUp() override {
8099 InputDispatcherTest::SetUp();
8100
8101 std::shared_ptr<FakeApplicationHandle> application =
8102 std::make_shared<FakeApplicationHandle>();
8103 application->setDispatchingTimeout(100ms);
8104 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
8105 ADISPLAY_ID_DEFAULT);
Yeabkal Wubshit222d83d2024-01-24 18:00:09 +00008106 mWindow->setFrame(Rect(0, 0, 100, 100));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08008107 mWindow->setDispatchingTimeout(100ms);
8108 mWindow->setFocusable(true);
8109
8110 // Set focused application.
8111 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8112
8113 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
8114 setFocusedWindow(mWindow);
8115 mWindow->consumeFocusEvent(true);
8116 }
8117
8118 void notifyAndConsumeMotion(int32_t action, uint32_t source, int32_t displayId,
8119 nsecs_t eventTime) {
8120 mDispatcher->notifyMotion(MotionArgsBuilder(action, source)
8121 .displayId(displayId)
8122 .eventTime(eventTime)
8123 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8124 .build());
8125 mWindow->consumeMotionEvent(WithMotionAction(action));
8126 }
8127
8128private:
8129 sp<FakeWindowHandle> mWindow;
8130};
8131
8132TEST_F_WITH_FLAGS(
8133 InputDispatcherUserActivityPokeTests, MinPokeTimeObserved,
8134 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8135 rate_limit_user_activity_poke_in_dispatcher))) {
8136 mDispatcher->setMinTimeBetweenUserActivityPokes(50ms);
8137
8138 // First event of type TOUCH. Should poke.
8139 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8140 milliseconds_to_nanoseconds(50));
8141 mFakePolicy->assertUserActivityPoked(
8142 {{milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8143
8144 // 80ns > 50ns has passed since previous TOUCH event. Should poke.
8145 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8146 milliseconds_to_nanoseconds(130));
8147 mFakePolicy->assertUserActivityPoked(
8148 {{milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8149
8150 // First event of type OTHER. Should poke (despite being within 50ns of previous TOUCH event).
8151 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8152 milliseconds_to_nanoseconds(135));
8153 mFakePolicy->assertUserActivityPoked(
8154 {{milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER, ADISPLAY_ID_DEFAULT}});
8155
8156 // Within 50ns of previous TOUCH event. Should NOT poke.
8157 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8158 milliseconds_to_nanoseconds(140));
8159 mFakePolicy->assertUserActivityNotPoked();
8160
8161 // Within 50ns of previous OTHER event. Should NOT poke.
8162 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8163 milliseconds_to_nanoseconds(150));
8164 mFakePolicy->assertUserActivityNotPoked();
8165
8166 // Within 50ns of previous TOUCH event (which was at time 130). Should NOT poke.
8167 // Note that STYLUS is mapped to TOUCH user activity, since it's a pointer-type source.
8168 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
8169 milliseconds_to_nanoseconds(160));
8170 mFakePolicy->assertUserActivityNotPoked();
8171
8172 // 65ns > 50ns has passed since previous OTHER event. Should poke.
8173 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8174 milliseconds_to_nanoseconds(200));
8175 mFakePolicy->assertUserActivityPoked(
8176 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER, ADISPLAY_ID_DEFAULT}});
8177
8178 // 170ns > 50ns has passed since previous TOUCH event. Should poke.
8179 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
8180 milliseconds_to_nanoseconds(300));
8181 mFakePolicy->assertUserActivityPoked(
8182 {{milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8183
8184 // Assert that there's no more user activity poke event.
8185 mFakePolicy->assertUserActivityNotPoked();
8186}
8187
8188TEST_F_WITH_FLAGS(
8189 InputDispatcherUserActivityPokeTests, DefaultMinPokeTimeOf100MsUsed,
8190 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8191 rate_limit_user_activity_poke_in_dispatcher))) {
8192 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8193 milliseconds_to_nanoseconds(200));
8194 mFakePolicy->assertUserActivityPoked(
8195 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8196
8197 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8198 milliseconds_to_nanoseconds(280));
8199 mFakePolicy->assertUserActivityNotPoked();
8200
8201 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8202 milliseconds_to_nanoseconds(340));
8203 mFakePolicy->assertUserActivityPoked(
8204 {{milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8205}
8206
8207TEST_F_WITH_FLAGS(
8208 InputDispatcherUserActivityPokeTests, ZeroMinPokeTimeDisablesRateLimiting,
8209 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8210 rate_limit_user_activity_poke_in_dispatcher))) {
8211 mDispatcher->setMinTimeBetweenUserActivityPokes(0ms);
8212
8213 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20);
8214 mFakePolicy->assertUserActivityPoked();
8215
8216 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 30);
8217 mFakePolicy->assertUserActivityPoked();
8218}
8219
chaviwfd6d3512019-03-25 13:23:49 -07008220class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008221 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07008222 InputDispatcherTest::SetUp();
8223
Chris Yea209fde2020-07-22 13:54:51 -07008224 std::shared_ptr<FakeApplicationHandle> application =
8225 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008226 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008227 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07008228 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07008229
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008230 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008231 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008232 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07008233
8234 // Set focused application.
8235 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07008236 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07008237
8238 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008239 mDispatcher->onWindowInfosChanged(
8240 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008241 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008242 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07008243 }
8244
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008245 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07008246 InputDispatcherTest::TearDown();
8247
8248 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008249 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07008250 }
8251
8252protected:
8253 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008254 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008255 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07008256};
8257
8258// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
8259// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
8260// the onPointerDownOutsideFocus callback.
8261TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008262 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008263 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008264 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008265 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008266 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008267
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008268 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07008269 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
8270}
8271
8272// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
8273// DOWN on the window that doesn't have focus. Ensure no window received the
8274// onPointerDownOutsideFocus callback.
8275TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008276 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008277 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
8278 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008279 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008280 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008281
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008282 ASSERT_TRUE(mDispatcher->waitForIdle());
8283 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008284}
8285
8286// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
8287// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
8288TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08008289 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008290 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008291 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008292 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07008293
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008294 ASSERT_TRUE(mDispatcher->waitForIdle());
8295 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008296}
8297
8298// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
8299// DOWN on the window that already has focus. Ensure no window received the
8300// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008301TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008302 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008303 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008304 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008305 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008306 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008307
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008308 ASSERT_TRUE(mDispatcher->waitForIdle());
8309 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008310}
8311
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008312// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
8313// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
8314TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
8315 const MotionEvent event =
8316 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
8317 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008318 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008319 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
8320 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008321 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008322 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8323 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
8324
8325 ASSERT_TRUE(mDispatcher->waitForIdle());
8326 mFakePolicy->assertOnPointerDownWasNotCalled();
8327 // Ensure that the unfocused window did not receive any FOCUS events.
8328 mUnfocusedWindow->assertNoEvents();
8329}
8330
chaviwaf87b3e2019-10-01 16:59:28 -07008331// These tests ensures we can send touch events to a single client when there are multiple input
8332// windows that point to the same client token.
8333class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
8334 virtual void SetUp() override {
8335 InputDispatcherTest::SetUp();
8336
Chris Yea209fde2020-07-22 13:54:51 -07008337 std::shared_ptr<FakeApplicationHandle> application =
8338 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008339 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
8340 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07008341 mWindow1->setFrame(Rect(0, 0, 100, 100));
8342
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00008343 mWindow2 = mWindow1->clone(ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07008344 mWindow2->setFrame(Rect(100, 100, 200, 200));
8345
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008346 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07008347 }
8348
8349protected:
8350 sp<FakeWindowHandle> mWindow1;
8351 sp<FakeWindowHandle> mWindow2;
8352
8353 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05008354 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07008355 vec2 vals = windowInfo->transform.transform(point.x, point.y);
8356 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07008357 }
8358
8359 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
8360 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008361 const std::string name = window->getName();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008362 std::unique_ptr<MotionEvent> motionEvent =
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008363 window->consumeMotionEvent(WithMotionAction(expectedAction));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008364 ASSERT_NE(nullptr, motionEvent);
8365 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07008366
8367 for (size_t i = 0; i < points.size(); i++) {
8368 float expectedX = points[i].x;
8369 float expectedY = points[i].y;
8370
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008371 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07008372 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008373 << ", got " << motionEvent->getX(i);
8374 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07008375 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008376 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07008377 }
8378 }
chaviw9eaa22c2020-07-01 16:21:27 -07008379
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008380 void touchAndAssertPositions(sp<FakeWindowHandle> touchedWindow, int32_t action,
8381 const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07008382 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008383 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
8384 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07008385
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008386 consumeMotionEvent(touchedWindow, action, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008387 }
chaviwaf87b3e2019-10-01 16:59:28 -07008388};
8389
8390TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
8391 // Touch Window 1
8392 PointF touchedPoint = {10, 10};
8393 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008394 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008395
8396 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008397 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008398
8399 // Touch Window 2
8400 touchedPoint = {150, 150};
8401 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008402 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008403}
8404
chaviw9eaa22c2020-07-01 16:21:27 -07008405TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
8406 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07008407 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008408 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07008409
8410 // Touch Window 1
8411 PointF touchedPoint = {10, 10};
8412 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008413 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008414 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008415 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008416
8417 // Touch Window 2
8418 touchedPoint = {150, 150};
8419 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008420 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
8421 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008422
chaviw9eaa22c2020-07-01 16:21:27 -07008423 // Update the transform so rotation is set
8424 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008425 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008426 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008427 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008428}
8429
chaviw9eaa22c2020-07-01 16:21:27 -07008430TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008431 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008432 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008433
8434 // Touch Window 1
8435 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8436 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008437 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008438
8439 // Touch Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008440 // Since this is part of the same touch gesture that has already been dispatched to Window 1,
8441 // the touch stream from Window 2 will be merged with the stream in Window 1. The merged stream
8442 // will continue to be dispatched through Window 1.
chaviw9eaa22c2020-07-01 16:21:27 -07008443 touchedPoints.push_back(PointF{150, 150});
8444 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008445 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008446
chaviw9eaa22c2020-07-01 16:21:27 -07008447 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008448 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008449 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008450
chaviw9eaa22c2020-07-01 16:21:27 -07008451 // Update the transform so rotation is set for Window 2
8452 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008453 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008454 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008455 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008456}
8457
chaviw9eaa22c2020-07-01 16:21:27 -07008458TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008459 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008460 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008461
8462 // Touch Window 1
8463 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8464 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008465 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008466
8467 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07008468 touchedPoints.push_back(PointF{150, 150});
8469 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008470
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008471 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008472
8473 // Move both windows
8474 touchedPoints = {{20, 20}, {175, 175}};
8475 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8476 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8477
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008478 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008479
chaviw9eaa22c2020-07-01 16:21:27 -07008480 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008481 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008482 expectedPoints.pop_back();
8483
8484 // Touch Window 2
8485 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008486 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008487 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008488 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008489
8490 // Move both windows
8491 touchedPoints = {{20, 20}, {175, 175}};
8492 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8493 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8494
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008495 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008496}
8497
8498TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
8499 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008500 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008501
8502 // Touch Window 1
8503 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8504 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008505 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008506
8507 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07008508 touchedPoints.push_back(PointF{150, 150});
8509 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008510
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008511 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008512
8513 // Move both windows
8514 touchedPoints = {{20, 20}, {175, 175}};
8515 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8516 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8517
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008518 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008519}
8520
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07008521/**
8522 * When one of the windows is slippery, the touch should not slip into the other window with the
8523 * same input channel.
8524 */
8525TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
8526 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008527 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07008528
8529 // Touch down in window 1
8530 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8531 ADISPLAY_ID_DEFAULT, {{50, 50}}));
8532 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
8533
8534 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
8535 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
8536 // getting generated.
8537 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8538 ADISPLAY_ID_DEFAULT, {{150, 150}}));
8539
8540 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
8541}
8542
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008543/**
8544 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
8545 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
8546 * that the pointer is hovering over may have a different transform.
8547 */
8548TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008549 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008550
8551 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008552 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
8553 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8554 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008555 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
8556 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008557 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008558 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8559 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
8560 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008561 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008562 consumeMotionEvent(mWindow2, ACTION_HOVER_ENTER,
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008563 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
8564}
8565
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008566class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
8567 virtual void SetUp() override {
8568 InputDispatcherTest::SetUp();
8569
Chris Yea209fde2020-07-22 13:54:51 -07008570 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008571 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008572 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
8573 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008574 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008575 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07008576 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008577
8578 // Set focused application.
8579 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8580
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008581 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008582 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008583 mWindow->consumeFocusEvent(true);
8584 }
8585
8586 virtual void TearDown() override {
8587 InputDispatcherTest::TearDown();
8588 mWindow.clear();
8589 }
8590
8591protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008592 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07008593 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008594 sp<FakeWindowHandle> mWindow;
8595 static constexpr PointF WINDOW_LOCATION = {20, 20};
8596
8597 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008598 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
8599 .x(WINDOW_LOCATION.x)
8600 .y(WINDOW_LOCATION.y);
8601 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8602 .pointer(touchingPointer)
8603 .build());
8604 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8605 .pointer(touchingPointer)
8606 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008607 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008608
8609 sp<FakeWindowHandle> addSpyWindow() {
8610 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008611 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008612 spy->setTrustedOverlay(true);
8613 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008614 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008615 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008616 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008617 return spy;
8618 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008619};
8620
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008621// Send a tap and respond, which should not cause an ANR.
8622TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
8623 tapOnWindow();
8624 mWindow->consumeMotionDown();
8625 mWindow->consumeMotionUp();
8626 ASSERT_TRUE(mDispatcher->waitForIdle());
8627 mFakePolicy->assertNotifyAnrWasNotCalled();
8628}
8629
8630// Send a regular key and respond, which should not cause an ANR.
8631TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008632 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008633 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8634 ASSERT_TRUE(mDispatcher->waitForIdle());
8635 mFakePolicy->assertNotifyAnrWasNotCalled();
8636}
8637
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008638TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
8639 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008640 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008641 mWindow->consumeFocusEvent(false);
8642
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008643 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008644 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8645 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00008646 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008647 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008648 // Key will not go to window because we have no focused window.
8649 // The 'no focused window' ANR timer should start instead.
8650
8651 // Now, the focused application goes away.
8652 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
8653 // The key should get dropped and there should be no ANR.
8654
8655 ASSERT_TRUE(mDispatcher->waitForIdle());
8656 mFakePolicy->assertNotifyAnrWasNotCalled();
8657}
8658
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008659// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008660// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8661// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008662TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008663 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008664 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008665 WINDOW_LOCATION));
8666
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008667 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008668 ASSERT_TRUE(sequenceNum);
8669 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008670 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008671
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008672 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008673 mWindow->consumeMotionEvent(
8674 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008675 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008676 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008677}
8678
8679// Send a key to the app and have the app not respond right away.
8680TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
8681 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008682 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008683 const auto [sequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008684 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008685 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008686 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008687 ASSERT_TRUE(mDispatcher->waitForIdle());
8688}
8689
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008690// We have a focused application, but no focused window
8691TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008692 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008693 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008694 mWindow->consumeFocusEvent(false);
8695
8696 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008697 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008698 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008699 WINDOW_LOCATION));
8700 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
8701 mDispatcher->waitForIdle();
8702 mFakePolicy->assertNotifyAnrWasNotCalled();
8703
8704 // Once a focused event arrives, we get an ANR for this application
8705 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8706 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008707 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008708 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008709 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008710 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008711 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07008712 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008713 ASSERT_TRUE(mDispatcher->waitForIdle());
8714}
8715
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008716/**
8717 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
8718 * there will not be an ANR.
8719 */
8720TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
8721 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008722 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008723 mWindow->consumeFocusEvent(false);
8724
8725 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07008726 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
8727 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008728 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
8729 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
8730
8731 // Define a valid key down event that is stale (too old).
8732 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00008733 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Hu Guofe3c8f12023-09-22 17:20:15 +08008734 AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008735
Hu Guofe3c8f12023-09-22 17:20:15 +08008736 const int32_t policyFlags =
8737 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008738
8739 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00008740 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008741 InputEventInjectionSync::WAIT_FOR_RESULT,
8742 INJECT_EVENT_TIMEOUT, policyFlags);
8743 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
8744 << "Injection should fail because the event is stale";
8745
8746 ASSERT_TRUE(mDispatcher->waitForIdle());
8747 mFakePolicy->assertNotifyAnrWasNotCalled();
8748 mWindow->assertNoEvents();
8749}
8750
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008751// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008752// Make sure that we don't notify policy twice about the same ANR.
8753TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008754 const std::chrono::duration appTimeout = 400ms;
8755 mApplication->setDispatchingTimeout(appTimeout);
8756 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8757
Vishnu Nair47074b82020-08-14 11:54:47 -07008758 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008759 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008760 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008761
8762 // Once a focused event arrives, we get an ANR for this application
8763 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8764 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008765 const std::chrono::duration eventInjectionTimeout = 100ms;
8766 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008767 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008768 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008769 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
8770 /*allowKeyRepeat=*/false);
8771 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
8772 << "result=" << ftl::enum_string(result);
8773 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
8774 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
8775 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
8776 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008777
Vishnu Naire4df8752022-09-08 09:17:55 -07008778 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008779 // ANR should not be raised again. It is up to policy to do that if it desires.
8780 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008781
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008782 // If we now get a focused window, the ANR should stop, but the policy handles that via
8783 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008784 ASSERT_TRUE(mDispatcher->waitForIdle());
8785}
8786
8787// We have a focused application, but no focused window
8788TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008789 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008790 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008791 mWindow->consumeFocusEvent(false);
8792
8793 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008794 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008795
Vishnu Naire4df8752022-09-08 09:17:55 -07008796 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8797 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008798
8799 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008800 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008801 ASSERT_TRUE(mDispatcher->waitForIdle());
8802 mWindow->assertNoEvents();
8803}
8804
8805/**
8806 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
8807 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
8808 * If we process 1 of the events, but ANR on the second event with the same timestamp,
8809 * the ANR mechanism should still work.
8810 *
8811 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
8812 * DOWN event, while not responding on the second one.
8813 */
8814TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
8815 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008816 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008817 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8818 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8819 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008820 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008821
8822 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008823 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008824 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8825 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8826 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008827 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008828
8829 // We have now sent down and up. Let's consume first event and then ANR on the second.
8830 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8831 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008832 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008833}
8834
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008835// A spy window can receive an ANR
8836TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
8837 sp<FakeWindowHandle> spy = addSpyWindow();
8838
8839 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008840 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008841 WINDOW_LOCATION));
8842 mWindow->consumeMotionDown();
8843
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008844 const auto [sequenceNum, _] = spy->receiveEvent(); // ACTION_DOWN
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008845 ASSERT_TRUE(sequenceNum);
8846 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008847 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008848
8849 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008850 spy->consumeMotionEvent(
8851 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008852 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008853 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008854}
8855
8856// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008857// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008858TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
8859 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008860
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008861 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008862 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008863 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008864 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008865
8866 // Stuck on the ACTION_UP
8867 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008868 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008869
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008870 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008871 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008872 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8873 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008874
8875 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8876 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008877 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008878 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008879 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008880}
8881
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008882// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008883// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008884TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
8885 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008886
8887 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008888 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8889 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008890
8891 mWindow->consumeMotionDown();
8892 // Stuck on the ACTION_UP
8893 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008894 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008895
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008896 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008897 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008898 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8899 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008900
8901 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8902 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008903 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008904 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008905 spy->assertNoEvents();
8906}
8907
8908TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008909 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008910
Prabir Pradhanfb549072023-10-05 19:17:36 +00008911 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008912
8913 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008914 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008915 WINDOW_LOCATION));
8916
8917 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8918 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
8919 ASSERT_TRUE(consumeSeq);
8920
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008921 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
8922 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008923
8924 monitor.finishEvent(*consumeSeq);
8925 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
8926
8927 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008928 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008929}
8930
8931// If a window is unresponsive, then you get anr. if the window later catches up and starts to
8932// process events, you don't get an anr. When the window later becomes unresponsive again, you
8933// get an ANR again.
8934// 1. tap -> block on ACTION_UP -> receive ANR
8935// 2. consume all pending events (= queue becomes healthy again)
8936// 3. tap again -> block on ACTION_UP again -> receive ANR second time
8937TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
8938 tapOnWindow();
8939
8940 mWindow->consumeMotionDown();
8941 // Block on ACTION_UP
8942 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008943 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008944 mWindow->consumeMotionUp(); // Now the connection should be healthy again
8945 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008946 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008947 mWindow->assertNoEvents();
8948
8949 tapOnWindow();
8950 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008951 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008952 mWindow->consumeMotionUp();
8953
8954 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008955 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008956 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008957 mWindow->assertNoEvents();
8958}
8959
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008960// If a connection remains unresponsive for a while, make sure policy is only notified once about
8961// it.
8962TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008963 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008964 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008965 WINDOW_LOCATION));
8966
8967 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008968 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008969 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008970 // 'notifyConnectionUnresponsive' should only be called once per connection
8971 mFakePolicy->assertNotifyAnrWasNotCalled();
8972 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008973 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008974 mWindow->consumeMotionEvent(
8975 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008976 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008977 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008978 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008979 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008980}
8981
8982/**
8983 * 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 -07008984 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008985 */
8986TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008987 // The timeouts in this test are established by relying on the fact that the "key waiting for
8988 // events timeout" is equal to 500ms.
8989 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008990 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008991 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008992
8993 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008994 const auto& [downSequenceNum, downEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008995 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008996 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008997 ASSERT_TRUE(upSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008998
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008999 // Don't finish the events yet, and send a key
9000 mDispatcher->notifyKey(
9001 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
9002 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9003 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009004 // Key will not be sent to the window, yet, because the window is still processing events
9005 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009006 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009007 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009008
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009009 std::this_thread::sleep_for(400ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009010 // if we wait long enough though, dispatcher will give up, and still send the key
9011 // to the focused window, even though we have not yet finished the motion event
9012 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9013 mWindow->finishEvent(*downSequenceNum);
9014 mWindow->finishEvent(*upSequenceNum);
9015}
9016
9017/**
9018 * If a window is processing a motion event, and then a key event comes in, the key event should
9019 * not go to the focused window until the motion is processed.
9020 * If then a new motion comes in, then the pending key event should be going to the currently
9021 * focused window right away.
9022 */
9023TEST_F(InputDispatcherSingleWindowAnr,
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009024 PendingKey_IsDeliveredWhileMotionIsProcessingAndNewTouchComesIn) {
9025 // The timeouts in this test are established by relying on the fact that the "key waiting for
9026 // events timeout" is equal to 500ms.
9027 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009028 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009029 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009030
9031 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009032 const auto& [downSequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009033 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009034 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009035 ASSERT_TRUE(upSequenceNum);
9036 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08009037 mDispatcher->notifyKey(
9038 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
9039 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9040 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009041 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009042 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009043
9044 // Now tap down again. It should cause the pending key to go to the focused window right away.
9045 tapOnWindow();
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009046 // Now that we tapped, we should receive the key immediately.
9047 // Since there's still room for slowness, we use 200ms, which is much less than
9048 // the "key waiting for events' timeout of 500ms minus the already waited 100ms duration.
9049 std::unique_ptr<InputEvent> keyEvent = mWindow->consume(200ms);
9050 ASSERT_NE(nullptr, keyEvent);
9051 ASSERT_EQ(InputEventType::KEY, keyEvent->getType());
9052 ASSERT_THAT(static_cast<KeyEvent&>(*keyEvent), WithKeyAction(AKEY_EVENT_ACTION_DOWN));
9053 // it doesn't matter that we haven't ack'd the other events yet. We can finish events in any
9054 // order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009055 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
9056 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08009057 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9058 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009059 mWindow->assertNoEvents();
9060}
9061
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07009062/**
9063 * Send an event to the app and have the app not respond right away.
9064 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
9065 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
9066 * At some point, the window becomes responsive again.
9067 * Ensure that subsequent events get dropped, and the next gesture is delivered.
9068 */
9069TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
9070 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9071 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
9072 .build());
9073
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009074 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07009075 ASSERT_TRUE(sequenceNum);
9076 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9077 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
9078
9079 mWindow->finishEvent(*sequenceNum);
9080 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
9081 ASSERT_TRUE(mDispatcher->waitForIdle());
9082 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
9083
9084 // Now that the window is responsive, let's continue the gesture.
9085 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9086 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9087 .build());
9088
9089 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9090 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9091 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
9092 .build());
9093
9094 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9095 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9096 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
9097 .build());
9098 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9099 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9100 .build());
9101 // We already canceled this pointer, so the window shouldn't get any new events.
9102 mWindow->assertNoEvents();
9103
9104 // Start another one.
9105 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9106 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
9107 .build());
9108 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9109}
9110
Prabir Pradhanfc364722024-02-08 17:51:20 +00009111// Send an event to the app and have the app not respond right away. Then remove the app window.
9112// When the window is removed, the dispatcher will cancel the events for that window.
9113// So InputDispatcher will enqueue ACTION_CANCEL event as well.
9114TEST_F(InputDispatcherSingleWindowAnr, AnrAfterWindowRemoval) {
9115 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9116 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9117 {WINDOW_LOCATION}));
9118
9119 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
9120 ASSERT_TRUE(sequenceNum);
9121
9122 // Remove the window, but the input channel should remain alive.
9123 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
9124
9125 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9126 // Since the window was removed, Dispatcher does not know the PID associated with the window
9127 // anymore, so the policy is notified without the PID.
9128 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken(),
9129 /*pid=*/std::nullopt);
9130
9131 mWindow->finishEvent(*sequenceNum);
9132 // The cancellation was generated when the window was removed, along with the focus event.
9133 mWindow->consumeMotionEvent(
9134 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
9135 mWindow->consumeFocusEvent(false);
9136 ASSERT_TRUE(mDispatcher->waitForIdle());
9137 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
9138}
9139
9140// Send an event to the app and have the app not respond right away. Wait for the policy to be
9141// notified of the unresponsive window, then remove the app window.
9142TEST_F(InputDispatcherSingleWindowAnr, AnrFollowedByWindowRemoval) {
9143 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9144 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9145 {WINDOW_LOCATION}));
9146
9147 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
9148 ASSERT_TRUE(sequenceNum);
9149 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9150 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
9151
9152 // Remove the window, but the input channel should remain alive.
9153 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
9154
9155 mWindow->finishEvent(*sequenceNum);
9156 // The cancellation was generated during the ANR, and the window lost focus when it was removed.
9157 mWindow->consumeMotionEvent(
9158 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
9159 mWindow->consumeFocusEvent(false);
9160 ASSERT_TRUE(mDispatcher->waitForIdle());
9161 // Since the window was removed, Dispatcher does not know the PID associated with the window
9162 // becoming responsive, so the policy is notified without the PID.
9163 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
9164}
9165
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009166class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
9167 virtual void SetUp() override {
9168 InputDispatcherTest::SetUp();
9169
Chris Yea209fde2020-07-22 13:54:51 -07009170 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009171 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009172 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
9173 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009174 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009175 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009176 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009177
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009178 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
9179 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009180 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009181 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009182
9183 // Set focused application.
9184 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07009185 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009186
9187 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009188 mDispatcher->onWindowInfosChanged(
9189 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009190 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009191 mFocusedWindow->consumeFocusEvent(true);
9192 }
9193
9194 virtual void TearDown() override {
9195 InputDispatcherTest::TearDown();
9196
9197 mUnfocusedWindow.clear();
9198 mFocusedWindow.clear();
9199 }
9200
9201protected:
Chris Yea209fde2020-07-22 13:54:51 -07009202 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009203 sp<FakeWindowHandle> mUnfocusedWindow;
9204 sp<FakeWindowHandle> mFocusedWindow;
9205 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
9206 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
9207 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
9208
9209 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
9210
9211 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
9212
9213private:
9214 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009215 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009216 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009217 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009218 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009219 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009220 location));
9221 }
9222};
9223
9224// If we have 2 windows that are both unresponsive, the one with the shortest timeout
9225// should be ANR'd first.
9226TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009227 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009228 injectMotionEvent(*mDispatcher,
9229 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9230 AINPUT_SOURCE_TOUCHSCREEN)
9231 .pointer(PointerBuilder(0, ToolType::FINGER)
9232 .x(FOCUSED_WINDOW_LOCATION.x)
9233 .y(FOCUSED_WINDOW_LOCATION.y))
9234 .build()));
9235 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9236 injectMotionEvent(*mDispatcher,
9237 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
9238 AINPUT_SOURCE_TOUCHSCREEN)
9239 .pointer(PointerBuilder(0, ToolType::FINGER)
9240 .x(FOCUSED_WINDOW_LOCATION.x)
9241 .y(FOCUSED_WINDOW_LOCATION.y))
9242 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009243 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009244 mFocusedWindow->consumeMotionUp();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009245 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009246 // We consumed all events, so no ANR
9247 ASSERT_TRUE(mDispatcher->waitForIdle());
9248 mFakePolicy->assertNotifyAnrWasNotCalled();
9249
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009250 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009251 injectMotionEvent(*mDispatcher,
9252 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9253 AINPUT_SOURCE_TOUCHSCREEN)
9254 .pointer(PointerBuilder(0, ToolType::FINGER)
9255 .x(FOCUSED_WINDOW_LOCATION.x)
9256 .y(FOCUSED_WINDOW_LOCATION.y))
9257 .build()));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009258 const auto [unfocusedSequenceNum, _] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009259 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009260
9261 const std::chrono::duration timeout =
9262 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009263 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009264
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009265 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009266 mFocusedWindow->consumeMotionDown();
9267 // This cancel is generated because the connection was unresponsive
9268 mFocusedWindow->consumeMotionCancel();
9269 mFocusedWindow->assertNoEvents();
9270 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009271 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009272 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9273 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009274 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009275}
9276
9277// If we have 2 windows with identical timeouts that are both unresponsive,
9278// it doesn't matter which order they should have ANR.
9279// But we should receive ANR for both.
9280TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
9281 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009282 mUnfocusedWindow->setDispatchingTimeout(
9283 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009284 mDispatcher->onWindowInfosChanged(
9285 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009286
9287 tapOnFocusedWindow();
9288 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009289 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009290 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
9291 mFocusedWindow->getDispatchingTimeout(
9292 DISPATCHING_TIMEOUT)),
9293 mFakePolicy->getUnresponsiveWindowToken(0ms)};
9294
9295 ASSERT_THAT(anrConnectionTokens,
9296 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
9297 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009298
9299 ASSERT_TRUE(mDispatcher->waitForIdle());
9300 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009301
9302 mFocusedWindow->consumeMotionDown();
9303 mFocusedWindow->consumeMotionUp();
9304 mUnfocusedWindow->consumeMotionOutside();
9305
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009306 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
9307 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009308
9309 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009310 ASSERT_THAT(responsiveTokens,
9311 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
9312 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009313 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009314}
9315
9316// If a window is already not responding, the second tap on the same window should be ignored.
9317// We should also log an error to account for the dropped event (not tested here).
9318// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
9319TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
9320 tapOnFocusedWindow();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009321 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009322 // Receive the events, but don't respond
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009323 const auto [downEventSequenceNum, downEvent] = mFocusedWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009324 ASSERT_TRUE(downEventSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009325 const auto [upEventSequenceNum, upEvent] = mFocusedWindow->receiveEvent(); // ACTION_UP
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009326 ASSERT_TRUE(upEventSequenceNum);
9327 const std::chrono::duration timeout =
9328 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009329 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009330
9331 // Tap once again
9332 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009333 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009334 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009335 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009336 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009337 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009338 FOCUSED_WINDOW_LOCATION));
9339 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
9340 // valid touch target
9341 mUnfocusedWindow->assertNoEvents();
9342
9343 // Consume the first tap
9344 mFocusedWindow->finishEvent(*downEventSequenceNum);
9345 mFocusedWindow->finishEvent(*upEventSequenceNum);
9346 ASSERT_TRUE(mDispatcher->waitForIdle());
9347 // The second tap did not go to the focused window
9348 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009349 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08009350 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9351 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009352 mFakePolicy->assertNotifyAnrWasNotCalled();
9353}
9354
9355// If you tap outside of all windows, there will not be ANR
9356TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009357 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009358 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009359 LOCATION_OUTSIDE_ALL_WINDOWS));
9360 ASSERT_TRUE(mDispatcher->waitForIdle());
9361 mFakePolicy->assertNotifyAnrWasNotCalled();
9362}
9363
9364// Since the focused window is paused, tapping on it should not produce any events
9365TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
9366 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009367 mDispatcher->onWindowInfosChanged(
9368 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009369
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009370 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009371 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009372 FOCUSED_WINDOW_LOCATION));
9373
9374 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
9375 ASSERT_TRUE(mDispatcher->waitForIdle());
9376 // Should not ANR because the window is paused, and touches shouldn't go to it
9377 mFakePolicy->assertNotifyAnrWasNotCalled();
9378
9379 mFocusedWindow->assertNoEvents();
9380 mUnfocusedWindow->assertNoEvents();
9381}
9382
9383/**
9384 * 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 -07009385 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009386 * If a different window becomes focused at this time, the key should go to that window instead.
9387 *
9388 * Warning!!!
9389 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
9390 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009391 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009392 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
9393 *
9394 * If that value changes, this test should also change.
9395 */
9396TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
9397 // Set a long ANR timeout to prevent it from triggering
9398 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009399 mDispatcher->onWindowInfosChanged(
9400 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009401
9402 tapOnUnfocusedWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009403 const auto [downSequenceNum, downEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009404 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009405 const auto [upSequenceNum, upEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009406 ASSERT_TRUE(upSequenceNum);
9407 // Don't finish the events yet, and send a key
9408 // Injection will succeed because we will eventually give up and send the key to the focused
9409 // window even if motions are still being processed.
9410
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009411 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009412 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9413 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009414 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009415 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009416 // and the key remains pending, waiting for the touch events to be processed.
9417 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
9418 // under the hood.
9419 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
9420 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009421
9422 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07009423 mFocusedWindow->setFocusable(false);
9424 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009425 mDispatcher->onWindowInfosChanged(
9426 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009427 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009428
9429 // Focus events should precede the key events
9430 mUnfocusedWindow->consumeFocusEvent(true);
9431 mFocusedWindow->consumeFocusEvent(false);
9432
9433 // Finish the tap events, which should unblock dispatcher
9434 mUnfocusedWindow->finishEvent(*downSequenceNum);
9435 mUnfocusedWindow->finishEvent(*upSequenceNum);
9436
9437 // Now that all queues are cleared and no backlog in the connections, the key event
9438 // can finally go to the newly focused "mUnfocusedWindow".
9439 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9440 mFocusedWindow->assertNoEvents();
9441 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009442 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009443}
9444
9445// When the touch stream is split across 2 windows, and one of them does not respond,
9446// then ANR should be raised and the touch should be canceled for the unresponsive window.
9447// The other window should not be affected by that.
9448TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
9449 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00009450 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9451 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9452 {FOCUSED_WINDOW_LOCATION}));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009453 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009454
9455 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00009456 mDispatcher->notifyMotion(
9457 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9458 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009459
9460 const std::chrono::duration timeout =
9461 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009462 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009463
9464 mUnfocusedWindow->consumeMotionDown();
9465 mFocusedWindow->consumeMotionDown();
9466 // Focused window may or may not receive ACTION_MOVE
9467 // But it should definitely receive ACTION_CANCEL due to the ANR
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009468 const auto [moveOrCancelSequenceNum, event] = mFocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009469 ASSERT_TRUE(moveOrCancelSequenceNum);
9470 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
9471 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009472 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009473 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
9474 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
9475 mFocusedWindow->consumeMotionCancel();
9476 } else {
9477 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
9478 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009479 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009480 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9481 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009482
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009483 mUnfocusedWindow->assertNoEvents();
9484 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009485 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009486}
9487
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009488/**
9489 * If we have no focused window, and a key comes in, we start the ANR timer.
9490 * The focused application should add a focused window before the timer runs out to prevent ANR.
9491 *
9492 * If the user touches another application during this time, the key should be dropped.
9493 * Next, if a new focused window comes in, without toggling the focused application,
9494 * then no ANR should occur.
9495 *
9496 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
9497 * but in some cases the policy may not update the focused application.
9498 */
9499TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
9500 std::shared_ptr<FakeApplicationHandle> focusedApplication =
9501 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07009502 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009503 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
9504 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
9505 mFocusedWindow->setFocusable(false);
9506
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009507 mDispatcher->onWindowInfosChanged(
9508 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009509 mFocusedWindow->consumeFocusEvent(false);
9510
9511 // Send a key. The ANR timer should start because there is no focused window.
9512 // 'focusedApplication' will get blamed if this timer completes.
9513 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009514 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009515 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9516 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00009517 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009518 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009519
9520 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
9521 // then the injected touches won't cause the focused event to get dropped.
9522 // The dispatcher only checks for whether the queue should be pruned upon queueing.
9523 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
9524 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
9525 // For this test, it means that the key would get delivered to the window once it becomes
9526 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009527 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009528
9529 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00009530 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9531 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9532 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009533
9534 // We do not consume the motion right away, because that would require dispatcher to first
9535 // process (== drop) the key event, and by that time, ANR will be raised.
9536 // Set the focused window first.
9537 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009538 mDispatcher->onWindowInfosChanged(
9539 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009540 setFocusedWindow(mFocusedWindow);
9541 mFocusedWindow->consumeFocusEvent(true);
9542 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
9543 // to another application. This could be a bug / behaviour in the policy.
9544
9545 mUnfocusedWindow->consumeMotionDown();
9546
9547 ASSERT_TRUE(mDispatcher->waitForIdle());
9548 // Should not ANR because we actually have a focused window. It was just added too slowly.
9549 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
9550}
9551
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -08009552/**
9553 * If we are pruning input queue, we should never drop pointer events. Otherwise, we risk having
9554 * an inconsistent event stream inside the dispatcher. In this test, we make sure that the
9555 * dispatcher doesn't prune pointer events incorrectly.
9556 *
9557 * This test reproduces a crash in InputDispatcher.
9558 * To reproduce the crash, we need to simulate the conditions for "pruning input queue" to occur.
9559 *
9560 * Keep the currently focused application (mApplication), and have no focused window.
9561 * We set up two additional windows:
9562 * 1) The navigation bar window. This simulates the system "NavigationBar", which is used in the
9563 * 3-button navigation mode. This window injects a BACK button when it's touched. 2) The application
9564 * window. This window is not focusable, but is touchable.
9565 *
9566 * We first touch the navigation bar, which causes it to inject a key. Since there's no focused
9567 * window, the dispatcher doesn't process this key, and all other events inside dispatcher are now
9568 * blocked. The dispatcher is waiting for 'mApplication' to add a focused window.
9569 *
9570 * Now, we touch "Another window". This window is owned by a different application than
9571 * 'mApplication'. This causes the dispatcher to stop waiting for 'mApplication' to add a focused
9572 * window. Now, the "pruning input queue" behaviour should kick in, and the dispatcher should start
9573 * dropping the events from its queue. Ensure that no crash occurs.
9574 *
9575 * In this test, we are setting long timeouts to prevent ANRs and events dropped due to being stale.
9576 * This does not affect the test running time.
9577 */
9578TEST_F(InputDispatcherMultiWindowAnr, PruningInputQueueShouldNotDropPointerEvents) {
9579 std::shared_ptr<FakeApplicationHandle> systemUiApplication =
9580 std::make_shared<FakeApplicationHandle>();
9581 systemUiApplication->setDispatchingTimeout(3000ms);
9582 mFakePolicy->setStaleEventTimeout(3000ms);
9583 sp<FakeWindowHandle> navigationBar =
9584 sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
9585 ADISPLAY_ID_DEFAULT);
9586 navigationBar->setFocusable(false);
9587 navigationBar->setWatchOutsideTouch(true);
9588 navigationBar->setFrame(Rect(0, 0, 100, 100));
9589
9590 mApplication->setDispatchingTimeout(3000ms);
9591 // 'mApplication' is already focused, but we call it again here to make it explicit.
9592 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
9593
9594 std::shared_ptr<FakeApplicationHandle> anotherApplication =
9595 std::make_shared<FakeApplicationHandle>();
9596 sp<FakeWindowHandle> appWindow =
9597 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
9598 ADISPLAY_ID_DEFAULT);
9599 appWindow->setFocusable(false);
9600 appWindow->setFrame(Rect(100, 100, 200, 200));
9601
9602 mDispatcher->onWindowInfosChanged(
9603 {{*navigationBar->getInfo(), *appWindow->getInfo()}, {}, 0, 0});
9604 // 'mFocusedWindow' is no longer in the dispatcher window list, and therefore loses focus
9605 mFocusedWindow->consumeFocusEvent(false);
9606
9607 // Touch down the navigation bar. It consumes the touch and injects a key into the dispatcher
9608 // in response.
9609 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9610 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9611 .build());
9612 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9613
9614 // Key will not be sent anywhere because we have no focused window. It will remain pending.
9615 // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
9616 InputEventInjectionResult result =
9617 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9618 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
9619 /*allowKeyRepeat=*/false);
9620 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
9621
9622 // Finish the gesture - lift up finger and inject ACTION_UP key event
9623 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9624 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9625 .build());
9626 result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9627 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
9628 /*allowKeyRepeat=*/false);
9629 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
9630 // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
9631 // getting any events yet.
9632 navigationBar->assertNoEvents();
9633
9634 // Now touch "Another window". This touch is going to a different application than the one we
9635 // are waiting for (which is 'mApplication').
9636 // This should cause the dispatcher to drop the pending focus-dispatched events (like the key
9637 // trying to be injected) and to continue processing the rest of the events in the original
9638 // order.
9639 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9640 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
9641 .build());
9642 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_UP));
9643 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
9644 appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9645
9646 appWindow->assertNoEvents();
9647 navigationBar->assertNoEvents();
9648}
9649
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009650// These tests ensure we cannot send touch events to a window that's positioned behind a window
9651// that has feature NO_INPUT_CHANNEL.
9652// Layout:
9653// Top (closest to user)
9654// mNoInputWindow (above all windows)
9655// mBottomWindow
9656// Bottom (furthest from user)
9657class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
9658 virtual void SetUp() override {
9659 InputDispatcherTest::SetUp();
9660
9661 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009662 mNoInputWindow =
9663 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
9664 "Window without input channel", ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009665 /*createInputChannel=*/false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009666 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009667 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
9668 // It's perfectly valid for this window to not have an associated input channel
9669
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009670 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
9671 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009672 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
9673
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009674 mDispatcher->onWindowInfosChanged(
9675 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009676 }
9677
9678protected:
9679 std::shared_ptr<FakeApplicationHandle> mApplication;
9680 sp<FakeWindowHandle> mNoInputWindow;
9681 sp<FakeWindowHandle> mBottomWindow;
9682};
9683
9684TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
9685 PointF touchedPoint = {10, 10};
9686
Prabir Pradhan678438e2023-04-13 19:32:51 +00009687 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9688 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9689 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009690
9691 mNoInputWindow->assertNoEvents();
9692 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
9693 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
9694 // and therefore should prevent mBottomWindow from receiving touches
9695 mBottomWindow->assertNoEvents();
9696}
9697
9698/**
9699 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
9700 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
9701 */
9702TEST_F(InputDispatcherMultiWindowOcclusionTests,
9703 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009704 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
9705 "Window with input channel and NO_INPUT_CHANNEL",
9706 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009707
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009708 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009709 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009710 mDispatcher->onWindowInfosChanged(
9711 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009712
9713 PointF touchedPoint = {10, 10};
9714
Prabir Pradhan678438e2023-04-13 19:32:51 +00009715 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9716 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9717 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009718
9719 mNoInputWindow->assertNoEvents();
9720 mBottomWindow->assertNoEvents();
9721}
9722
Vishnu Nair958da932020-08-21 17:12:37 -07009723class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
9724protected:
9725 std::shared_ptr<FakeApplicationHandle> mApp;
9726 sp<FakeWindowHandle> mWindow;
9727 sp<FakeWindowHandle> mMirror;
9728
9729 virtual void SetUp() override {
9730 InputDispatcherTest::SetUp();
9731 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009732 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009733 mMirror = mWindow->clone(ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07009734 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
9735 mWindow->setFocusable(true);
9736 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009737 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009738 }
9739};
9740
9741TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
9742 // Request focus on a mirrored window
9743 setFocusedWindow(mMirror);
9744
9745 // window gets focused
9746 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009747 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009748 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009749 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
9750}
9751
9752// A focused & mirrored window remains focused only if the window and its mirror are both
9753// focusable.
9754TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
9755 setFocusedWindow(mMirror);
9756
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009757 // window gets focused because it is above the mirror
Vishnu Nair958da932020-08-21 17:12:37 -07009758 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009759 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009760 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009761 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009762 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009763 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009764 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9765
9766 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009767 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009768
9769 // window loses focus since one of the windows associated with the token in not focusable
9770 mWindow->consumeFocusEvent(false);
9771
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009772 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009773 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009774 mWindow->assertNoEvents();
9775}
9776
9777// A focused & mirrored window remains focused until the window and its mirror both become
9778// invisible.
9779TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
9780 setFocusedWindow(mMirror);
9781
9782 // window gets focused
9783 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009784 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009785 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009786 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009787 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009788 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009789 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9790
9791 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009792 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009793
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009794 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009795 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009796 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009797 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009798 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009799 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9800
9801 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009802 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009803
9804 // window loses focus only after all windows associated with the token become invisible.
9805 mWindow->consumeFocusEvent(false);
9806
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009807 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009808 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009809 mWindow->assertNoEvents();
9810}
9811
9812// A focused & mirrored window remains focused until both windows are removed.
9813TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
9814 setFocusedWindow(mMirror);
9815
9816 // window gets focused
9817 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009818 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009819 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009820 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009821 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009822 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009823 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9824
9825 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009826 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009827
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009828 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009829 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009830 mMirror->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009831 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009832 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009833 mMirror->consumeKeyUp(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07009834
9835 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009836 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009837 mWindow->consumeFocusEvent(false);
9838
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009839 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009840 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009841 mWindow->assertNoEvents();
9842}
9843
9844// Focus request can be pending until one window becomes visible.
9845TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
9846 // Request focus on an invisible mirror.
9847 mWindow->setVisible(false);
9848 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009849 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009850 setFocusedWindow(mMirror);
9851
9852 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009853 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009854 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9855 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07009856
9857 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009858 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009859
9860 // window gets focused
9861 mWindow->consumeFocusEvent(true);
9862 // window gets the pending key event
9863 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9864}
Prabir Pradhan99987712020-11-10 18:43:05 -08009865
9866class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
9867protected:
9868 std::shared_ptr<FakeApplicationHandle> mApp;
9869 sp<FakeWindowHandle> mWindow;
9870 sp<FakeWindowHandle> mSecondWindow;
9871
9872 void SetUp() override {
9873 InputDispatcherTest::SetUp();
9874 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009875 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009876 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009877 mSecondWindow =
9878 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009879 mSecondWindow->setFocusable(true);
9880
9881 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009882 mDispatcher->onWindowInfosChanged(
9883 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08009884
9885 setFocusedWindow(mWindow);
9886 mWindow->consumeFocusEvent(true);
9887 }
9888
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009889 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009890 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08009891 }
9892
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009893 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
9894 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08009895 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Hiroki Sato25040232024-02-22 17:21:22 +09009896 auto request = mFakePolicy->assertSetPointerCaptureCalled(window, enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009897 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009898 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009899 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08009900 }
9901};
9902
9903TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
9904 // Ensure that capture cannot be obtained for unfocused windows.
9905 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
9906 mFakePolicy->assertSetPointerCaptureNotCalled();
9907 mSecondWindow->assertNoEvents();
9908
9909 // Ensure that capture can be enabled from the focus window.
9910 requestAndVerifyPointerCapture(mWindow, true);
9911
9912 // Ensure that capture cannot be disabled from a window that does not have capture.
9913 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
9914 mFakePolicy->assertSetPointerCaptureNotCalled();
9915
9916 // Ensure that capture can be disabled from the window with capture.
9917 requestAndVerifyPointerCapture(mWindow, false);
9918}
9919
9920TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009921 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009922
9923 setFocusedWindow(mSecondWindow);
9924
9925 // Ensure that the capture disabled event was sent first.
9926 mWindow->consumeCaptureEvent(false);
9927 mWindow->consumeFocusEvent(false);
9928 mSecondWindow->consumeFocusEvent(true);
Hiroki Sato25040232024-02-22 17:21:22 +09009929 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009930
9931 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009932 notifyPointerCaptureChanged({});
9933 notifyPointerCaptureChanged(request);
9934 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08009935 mWindow->assertNoEvents();
9936 mSecondWindow->assertNoEvents();
9937 mFakePolicy->assertSetPointerCaptureNotCalled();
9938}
9939
9940TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009941 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009942
9943 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009944 notifyPointerCaptureChanged({});
9945 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009946
9947 // Ensure that Pointer Capture is disabled.
Hiroki Sato25040232024-02-22 17:21:22 +09009948 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009949 mWindow->consumeCaptureEvent(false);
9950 mWindow->assertNoEvents();
9951}
9952
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009953TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
9954 requestAndVerifyPointerCapture(mWindow, true);
9955
9956 // The first window loses focus.
9957 setFocusedWindow(mSecondWindow);
Hiroki Sato25040232024-02-22 17:21:22 +09009958 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009959 mWindow->consumeCaptureEvent(false);
9960
9961 // Request Pointer Capture from the second window before the notification from InputReader
9962 // arrives.
9963 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +09009964 auto request = mFakePolicy->assertSetPointerCaptureCalled(mSecondWindow, true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009965
9966 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009967 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009968
9969 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009970 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009971
9972 mSecondWindow->consumeFocusEvent(true);
9973 mSecondWindow->consumeCaptureEvent(true);
9974}
9975
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009976TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
9977 // App repeatedly enables and disables capture.
9978 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +09009979 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009980 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
Hiroki Sato25040232024-02-22 17:21:22 +09009981 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009982 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +09009983 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009984
9985 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
9986 // first request is now stale, this should do nothing.
9987 notifyPointerCaptureChanged(firstRequest);
9988 mWindow->assertNoEvents();
9989
9990 // InputReader notifies that the second request was enabled.
9991 notifyPointerCaptureChanged(secondRequest);
9992 mWindow->consumeCaptureEvent(true);
9993}
9994
Prabir Pradhan7092e262022-05-03 16:51:09 +00009995TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
9996 requestAndVerifyPointerCapture(mWindow, true);
9997
9998 // App toggles pointer capture off and on.
9999 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
Hiroki Sato25040232024-02-22 17:21:22 +090010000 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan7092e262022-05-03 16:51:09 +000010001
10002 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090010003 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan7092e262022-05-03 16:51:09 +000010004
10005 // InputReader notifies that the latest "enable" request was processed, while skipping over the
10006 // preceding "disable" request.
10007 notifyPointerCaptureChanged(enableRequest);
10008
10009 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
10010 // any notifications.
10011 mWindow->assertNoEvents();
10012}
10013
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010014/**
10015 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
10016 * mouse movements don't affect the previous mouse hovering state.
10017 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
10018 * HOVER_MOVE events).
10019 */
10020TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
10021 // Mouse hover on the window
10022 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
10023 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
10024 .build());
10025 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
10026 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
10027 .build());
10028
10029 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
10030 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
10031
10032 // Start pointer capture
10033 requestAndVerifyPointerCapture(mWindow, true);
10034
10035 // Send some relative mouse movements and receive them in the window.
10036 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
10037 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
10038 .build());
10039 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
10040 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
10041
10042 // Stop pointer capture
10043 requestAndVerifyPointerCapture(mWindow, false);
10044
10045 // Continue hovering on the window
10046 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
10047 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
10048 .build());
10049 mWindow->consumeMotionEvent(
10050 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
10051
10052 mWindow->assertNoEvents();
10053}
10054
Hiroki Sato25040232024-02-22 17:21:22 +090010055using InputDispatcherPointerCaptureDeathTest = InputDispatcherPointerCaptureTests;
10056
10057TEST_F(InputDispatcherPointerCaptureDeathTest,
10058 NotifyPointerCaptureChangedWithWrongTokenAbortsDispatcher) {
10059 testing::GTEST_FLAG(death_test_style) = "threadsafe";
10060 ScopedSilentDeath _silentDeath;
10061
10062 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
10063 auto request = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
10064
10065 // Dispatch a pointer changed event with a wrong token.
10066 request.window = mSecondWindow->getToken();
10067 ASSERT_DEATH(
10068 {
10069 notifyPointerCaptureChanged(request);
10070 mSecondWindow->consumeCaptureEvent(true);
10071 },
10072 "Unexpected requested window for Pointer Capture.");
10073}
10074
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010075class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
10076protected:
10077 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +000010078
10079 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
10080 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
10081
10082 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
10083 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
10084
10085 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
10086 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
10087 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
10088 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
10089 MAXIMUM_OBSCURING_OPACITY);
10090
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010091 static constexpr gui::Uid TOUCHED_APP_UID{10001};
10092 static constexpr gui::Uid APP_B_UID{10002};
10093 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010094
10095 sp<FakeWindowHandle> mTouchWindow;
10096
10097 virtual void SetUp() override {
10098 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010099 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010100 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
10101 }
10102
10103 virtual void TearDown() override {
10104 InputDispatcherTest::TearDown();
10105 mTouchWindow.clear();
10106 }
10107
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010108 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -050010109 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010110 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010111 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010112 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010113 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010114 return window;
10115 }
10116
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010117 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010118 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
10119 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010120 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010121 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010122 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010123 return window;
10124 }
10125
10126 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010127 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10128 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10129 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010130 }
10131};
10132
10133TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010134 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010135 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010136 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010137
10138 touch();
10139
10140 mTouchWindow->assertNoEvents();
10141}
10142
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010143TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +000010144 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
10145 const sp<FakeWindowHandle>& w =
10146 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010147 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010148
10149 touch();
10150
10151 mTouchWindow->assertNoEvents();
10152}
10153
10154TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010155 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
10156 const sp<FakeWindowHandle>& w =
10157 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010158 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010159
10160 touch();
10161
10162 w->assertNoEvents();
10163}
10164
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010165TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010166 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010167 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010168
10169 touch();
10170
10171 mTouchWindow->consumeAnyMotionDown();
10172}
10173
10174TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010175 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010176 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010177 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010178 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010179
10180 touch({PointF{100, 100}});
10181
10182 mTouchWindow->consumeAnyMotionDown();
10183}
10184
10185TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010186 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010187 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010188 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010189
10190 touch();
10191
10192 mTouchWindow->consumeAnyMotionDown();
10193}
10194
10195TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
10196 const sp<FakeWindowHandle>& w =
10197 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010198 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010199
10200 touch();
10201
10202 mTouchWindow->consumeAnyMotionDown();
10203}
10204
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010205TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
10206 const sp<FakeWindowHandle>& w =
10207 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010208 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010209
10210 touch();
10211
10212 w->assertNoEvents();
10213}
10214
10215/**
10216 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
10217 * inside) while letting them pass-through. Note that even though touch passes through the occluding
10218 * window, the occluding window will still receive ACTION_OUTSIDE event.
10219 */
10220TEST_F(InputDispatcherUntrustedTouchesTest,
10221 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
10222 const sp<FakeWindowHandle>& w =
10223 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010224 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010225 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010226
10227 touch();
10228
10229 w->consumeMotionOutside();
10230}
10231
10232TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
10233 const sp<FakeWindowHandle>& w =
10234 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010235 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010236 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010237
10238 touch();
10239
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010240 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010241}
10242
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010243TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010244 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010245 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10246 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010247 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010248
10249 touch();
10250
10251 mTouchWindow->consumeAnyMotionDown();
10252}
10253
10254TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
10255 const sp<FakeWindowHandle>& w =
10256 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10257 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010258 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010259
10260 touch();
10261
10262 mTouchWindow->consumeAnyMotionDown();
10263}
10264
10265TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010266 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010267 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10268 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010269 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010270
10271 touch();
10272
10273 mTouchWindow->assertNoEvents();
10274}
10275
10276TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
10277 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
10278 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010279 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
10280 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010281 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010282 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
10283 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010284 mDispatcher->onWindowInfosChanged(
10285 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010286
10287 touch();
10288
10289 mTouchWindow->assertNoEvents();
10290}
10291
10292TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
10293 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
10294 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010295 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
10296 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010297 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010298 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
10299 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010300 mDispatcher->onWindowInfosChanged(
10301 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010302
10303 touch();
10304
10305 mTouchWindow->consumeAnyMotionDown();
10306}
10307
10308TEST_F(InputDispatcherUntrustedTouchesTest,
10309 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
10310 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010311 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10312 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010313 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010314 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10315 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010316 mDispatcher->onWindowInfosChanged(
10317 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010318
10319 touch();
10320
10321 mTouchWindow->consumeAnyMotionDown();
10322}
10323
10324TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
10325 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010326 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10327 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010328 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010329 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10330 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010331 mDispatcher->onWindowInfosChanged(
10332 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010333
10334 touch();
10335
10336 mTouchWindow->assertNoEvents();
10337}
10338
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010339TEST_F(InputDispatcherUntrustedTouchesTest,
10340 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
10341 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010342 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10343 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010344 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010345 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10346 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010347 mDispatcher->onWindowInfosChanged(
10348 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010349
10350 touch();
10351
10352 mTouchWindow->assertNoEvents();
10353}
10354
10355TEST_F(InputDispatcherUntrustedTouchesTest,
10356 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
10357 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010358 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10359 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010360 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010361 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10362 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010363 mDispatcher->onWindowInfosChanged(
10364 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010365
10366 touch();
10367
10368 mTouchWindow->consumeAnyMotionDown();
10369}
10370
10371TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
10372 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010373 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10374 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010375 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010376
10377 touch();
10378
10379 mTouchWindow->consumeAnyMotionDown();
10380}
10381
10382TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
10383 const sp<FakeWindowHandle>& w =
10384 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010385 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010386
10387 touch();
10388
10389 mTouchWindow->consumeAnyMotionDown();
10390}
10391
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010392TEST_F(InputDispatcherUntrustedTouchesTest,
10393 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
10394 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
10395 const sp<FakeWindowHandle>& w =
10396 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010397 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010398
10399 touch();
10400
10401 mTouchWindow->assertNoEvents();
10402}
10403
10404TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
10405 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
10406 const sp<FakeWindowHandle>& w =
10407 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010408 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010409
10410 touch();
10411
10412 mTouchWindow->consumeAnyMotionDown();
10413}
10414
10415TEST_F(InputDispatcherUntrustedTouchesTest,
10416 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
10417 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
10418 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010419 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10420 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010421 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010422
10423 touch();
10424
10425 mTouchWindow->consumeAnyMotionDown();
10426}
10427
10428TEST_F(InputDispatcherUntrustedTouchesTest,
10429 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
10430 const sp<FakeWindowHandle>& w1 =
10431 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
10432 OPACITY_BELOW_THRESHOLD);
10433 const sp<FakeWindowHandle>& w2 =
10434 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10435 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010436 mDispatcher->onWindowInfosChanged(
10437 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010438
10439 touch();
10440
10441 mTouchWindow->assertNoEvents();
10442}
10443
10444/**
10445 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
10446 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
10447 * (which alone would result in allowing touches) does not affect the blocking behavior.
10448 */
10449TEST_F(InputDispatcherUntrustedTouchesTest,
10450 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
10451 const sp<FakeWindowHandle>& wB =
10452 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
10453 OPACITY_BELOW_THRESHOLD);
10454 const sp<FakeWindowHandle>& wC =
10455 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10456 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010457 mDispatcher->onWindowInfosChanged(
10458 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010459
10460 touch();
10461
10462 mTouchWindow->assertNoEvents();
10463}
10464
10465/**
10466 * This test is testing that a window from a different UID but with same application token doesn't
10467 * block the touch. Apps can share the application token for close UI collaboration for example.
10468 */
10469TEST_F(InputDispatcherUntrustedTouchesTest,
10470 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
10471 const sp<FakeWindowHandle>& w =
10472 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
10473 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010474 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010475
10476 touch();
10477
10478 mTouchWindow->consumeAnyMotionDown();
10479}
10480
arthurhungb89ccb02020-12-30 16:19:01 +080010481class InputDispatcherDragTests : public InputDispatcherTest {
10482protected:
10483 std::shared_ptr<FakeApplicationHandle> mApp;
10484 sp<FakeWindowHandle> mWindow;
10485 sp<FakeWindowHandle> mSecondWindow;
10486 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010487 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010488 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
10489 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +080010490
10491 void SetUp() override {
10492 InputDispatcherTest::SetUp();
10493 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010494 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080010495 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080010496
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010497 mSecondWindow =
10498 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080010499 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080010500
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010501 mSpyWindow =
10502 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010503 mSpyWindow->setSpy(true);
10504 mSpyWindow->setTrustedOverlay(true);
10505 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
10506
arthurhungb89ccb02020-12-30 16:19:01 +080010507 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010508 mDispatcher->onWindowInfosChanged(
10509 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
10510 {},
10511 0,
10512 0});
arthurhungb89ccb02020-12-30 16:19:01 +080010513 }
10514
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010515 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
10516 switch (fromSource) {
10517 case AINPUT_SOURCE_TOUCHSCREEN:
10518 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010519 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010520 ADISPLAY_ID_DEFAULT, {50, 50}))
10521 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10522 break;
10523 case AINPUT_SOURCE_STYLUS:
10524 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010525 injectMotionEvent(*mDispatcher,
10526 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10527 AINPUT_SOURCE_STYLUS)
10528 .buttonState(
10529 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
10530 .pointer(PointerBuilder(0, ToolType::STYLUS)
10531 .x(50)
10532 .y(50))
10533 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010534 break;
10535 case AINPUT_SOURCE_MOUSE:
10536 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010537 injectMotionEvent(*mDispatcher,
10538 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10539 AINPUT_SOURCE_MOUSE)
10540 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
10541 .pointer(PointerBuilder(MOUSE_POINTER_ID,
10542 ToolType::MOUSE)
10543 .x(50)
10544 .y(50))
10545 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010546 break;
10547 default:
10548 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
10549 }
arthurhungb89ccb02020-12-30 16:19:01 +080010550
10551 // Window should receive motion event.
10552 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010553 // Spy window should also receive motion event
10554 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000010555 }
10556
10557 // Start performing drag, we will create a drag window and transfer touch to it.
10558 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
10559 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010560 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +000010561 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010562 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +000010563 }
arthurhungb89ccb02020-12-30 16:19:01 +080010564
10565 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010566 mDragWindow =
10567 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010568 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010569 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
10570 *mWindow->getInfo(), *mSecondWindow->getInfo()},
10571 {},
10572 0,
10573 0});
arthurhungb89ccb02020-12-30 16:19:01 +080010574
10575 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +000010576 bool transferred =
Prabir Pradhan367f3432024-02-13 23:05:58 +000010577 mDispatcher->transferTouchGesture(mWindow->getToken(), mDragWindow->getToken(),
10578 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +000010579 if (transferred) {
10580 mWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +000010581 mDragWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000010582 }
10583 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +080010584 }
10585};
10586
10587TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010588 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +080010589
10590 // Move on window.
10591 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010592 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010593 ADISPLAY_ID_DEFAULT, {50, 50}))
10594 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010595 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080010596 mWindow->consumeDragEvent(false, 50, 50);
10597 mSecondWindow->assertNoEvents();
10598
10599 // Move to another window.
10600 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010601 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010602 ADISPLAY_ID_DEFAULT, {150, 50}))
10603 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010604 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080010605 mWindow->consumeDragEvent(true, 150, 50);
10606 mSecondWindow->consumeDragEvent(false, 50, 50);
10607
10608 // Move back to original window.
10609 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010610 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010611 ADISPLAY_ID_DEFAULT, {50, 50}))
10612 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010613 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080010614 mWindow->consumeDragEvent(false, 50, 50);
10615 mSecondWindow->consumeDragEvent(true, -50, 50);
10616
10617 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010618 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10619 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080010620 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010621 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080010622 mWindow->assertNoEvents();
10623 mSecondWindow->assertNoEvents();
10624}
10625
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010626TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010627 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010628
10629 // No cancel event after drag start
10630 mSpyWindow->assertNoEvents();
10631
10632 const MotionEvent secondFingerDownEvent =
10633 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10634 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010635 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10636 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010637 .build();
10638 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010639 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010640 InputEventInjectionSync::WAIT_FOR_RESULT))
10641 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10642
10643 // Receives cancel for first pointer after next pointer down
10644 mSpyWindow->consumeMotionCancel();
10645 mSpyWindow->consumeMotionDown();
10646
10647 mSpyWindow->assertNoEvents();
10648}
10649
arthurhungf452d0b2021-01-06 00:19:52 +080010650TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010651 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +080010652
10653 // Move on window.
10654 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010655 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +080010656 ADISPLAY_ID_DEFAULT, {50, 50}))
10657 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010658 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080010659 mWindow->consumeDragEvent(false, 50, 50);
10660 mSecondWindow->assertNoEvents();
10661
10662 // Move to another window.
10663 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010664 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +080010665 ADISPLAY_ID_DEFAULT, {150, 50}))
10666 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010667 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080010668 mWindow->consumeDragEvent(true, 150, 50);
10669 mSecondWindow->consumeDragEvent(false, 50, 50);
10670
10671 // drop to another window.
10672 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010673 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +080010674 {150, 50}))
10675 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010676 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010677 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +080010678 mWindow->assertNoEvents();
10679 mSecondWindow->assertNoEvents();
10680}
10681
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010682TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
10683 startDrag();
10684
10685 // No cancel event after drag start
10686 mSpyWindow->assertNoEvents();
10687
10688 const MotionEvent secondFingerDownEvent =
10689 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10690 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10691 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10692 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10693 .build();
10694 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10695 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10696 InputEventInjectionSync::WAIT_FOR_RESULT))
10697 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10698
10699 // Receives cancel for first pointer after next pointer down
10700 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080010701 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010702 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
10703
10704 mSpyWindow->assertNoEvents();
10705
10706 // Spy window calls pilfer pointers
10707 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
10708 mDragWindow->assertNoEvents();
10709
10710 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010711 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010712 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10713 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
10714 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10715 .build();
10716 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010717 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010718 InputEventInjectionSync::WAIT_FOR_RESULT))
10719 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10720
10721 // Drag window should still receive the new event
Prabir Pradhan65455c72024-02-13 21:46:41 +000010722 mDragWindow->consumeMotionEvent(
10723 AllOf(WithMotionAction(ACTION_MOVE), WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010724 mDragWindow->assertNoEvents();
10725}
10726
arthurhung6d4bed92021-03-17 11:59:33 +080010727TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010728 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +080010729
10730 // Move on window and keep button pressed.
10731 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010732 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010733 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10734 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010735 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010736 .build()))
10737 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010738 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080010739 mWindow->consumeDragEvent(false, 50, 50);
10740 mSecondWindow->assertNoEvents();
10741
10742 // Move to another window and release button, expect to drop item.
10743 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010744 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010745 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10746 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010747 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010748 .build()))
10749 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010750 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080010751 mWindow->assertNoEvents();
10752 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010753 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +080010754
10755 // nothing to the window.
10756 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010757 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010758 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
10759 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010760 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010761 .build()))
10762 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010763 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080010764 mWindow->assertNoEvents();
10765 mSecondWindow->assertNoEvents();
10766}
10767
Arthur Hung54745652022-04-20 07:17:41 +000010768TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010769 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +080010770
10771 // Set second window invisible.
10772 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010773 mDispatcher->onWindowInfosChanged(
10774 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +080010775
10776 // Move on window.
10777 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010778 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010779 ADISPLAY_ID_DEFAULT, {50, 50}))
10780 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010781 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010782 mWindow->consumeDragEvent(false, 50, 50);
10783 mSecondWindow->assertNoEvents();
10784
10785 // Move to another window.
10786 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010787 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010788 ADISPLAY_ID_DEFAULT, {150, 50}))
10789 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010790 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010791 mWindow->consumeDragEvent(true, 150, 50);
10792 mSecondWindow->assertNoEvents();
10793
10794 // drop to another window.
10795 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010796 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010797 {150, 50}))
10798 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010799 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010800 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010801 mWindow->assertNoEvents();
10802 mSecondWindow->assertNoEvents();
10803}
10804
Arthur Hung54745652022-04-20 07:17:41 +000010805TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010806 // Ensure window could track pointerIds if it didn't support split touch.
10807 mWindow->setPreventSplitting(true);
10808
Arthur Hung54745652022-04-20 07:17:41 +000010809 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010810 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010811 {50, 50}))
10812 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10813 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10814
10815 const MotionEvent secondFingerDownEvent =
10816 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10817 .displayId(ADISPLAY_ID_DEFAULT)
10818 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010819 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10820 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010821 .build();
10822 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010823 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010824 InputEventInjectionSync::WAIT_FOR_RESULT))
10825 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010826 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +000010827
10828 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010829 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010830}
10831
10832TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
10833 // First down on second window.
10834 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010835 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010836 {150, 50}))
10837 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10838
10839 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10840
10841 // Second down on first window.
10842 const MotionEvent secondFingerDownEvent =
10843 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10844 .displayId(ADISPLAY_ID_DEFAULT)
10845 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010846 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10847 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010848 .build();
10849 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010850 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010851 InputEventInjectionSync::WAIT_FOR_RESULT))
10852 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10853 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +000010854 mSecondWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000010855
10856 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010857 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010858
10859 // Move on window.
10860 const MotionEvent secondFingerMoveEvent =
10861 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10862 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010863 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10864 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010865 .build();
10866 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010867 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010868 InputEventInjectionSync::WAIT_FOR_RESULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +000010869 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000010870 mWindow->consumeDragEvent(false, 50, 50);
10871 mSecondWindow->consumeMotionMove();
10872
10873 // Release the drag pointer should perform drop.
10874 const MotionEvent secondFingerUpEvent =
10875 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10876 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010877 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10878 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010879 .build();
10880 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010881 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010882 InputEventInjectionSync::WAIT_FOR_RESULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +000010883 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010884 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000010885 mWindow->assertNoEvents();
10886 mSecondWindow->consumeMotionMove();
10887}
10888
Arthur Hung3915c1f2022-05-31 07:17:17 +000010889TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010890 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000010891
10892 // Update window of second display.
10893 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010894 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010895 mDispatcher->onWindowInfosChanged(
10896 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10897 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10898 {},
10899 0,
10900 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010901
10902 // Let second display has a touch state.
10903 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010904 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010905 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10906 AINPUT_SOURCE_TOUCHSCREEN)
10907 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010908 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000010909 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000010910 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010911 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010912 mDispatcher->onWindowInfosChanged(
10913 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10914 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10915 {},
10916 0,
10917 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010918
10919 // Move on window.
10920 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010921 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010922 ADISPLAY_ID_DEFAULT, {50, 50}))
10923 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010924 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010925 mWindow->consumeDragEvent(false, 50, 50);
10926 mSecondWindow->assertNoEvents();
10927
10928 // Move to another window.
10929 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010930 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010931 ADISPLAY_ID_DEFAULT, {150, 50}))
10932 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010933 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010934 mWindow->consumeDragEvent(true, 150, 50);
10935 mSecondWindow->consumeDragEvent(false, 50, 50);
10936
10937 // drop to another window.
10938 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010939 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010940 {150, 50}))
10941 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010942 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010943 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000010944 mWindow->assertNoEvents();
10945 mSecondWindow->assertNoEvents();
10946}
10947
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010948TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
10949 startDrag(true, AINPUT_SOURCE_MOUSE);
10950 // Move on window.
10951 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010952 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010953 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10954 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010955 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010956 .x(50)
10957 .y(50))
10958 .build()))
10959 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010960 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010961 mWindow->consumeDragEvent(false, 50, 50);
10962 mSecondWindow->assertNoEvents();
10963
10964 // Move to another window.
10965 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010966 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010967 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10968 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010969 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010970 .x(150)
10971 .y(50))
10972 .build()))
10973 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010974 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010975 mWindow->consumeDragEvent(true, 150, 50);
10976 mSecondWindow->consumeDragEvent(false, 50, 50);
10977
10978 // drop to another window.
10979 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010980 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010981 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
10982 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010983 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010984 .x(150)
10985 .y(50))
10986 .build()))
10987 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010988 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010989 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010990 mWindow->assertNoEvents();
10991 mSecondWindow->assertNoEvents();
10992}
10993
Linnan Li5af92f92023-07-14 14:36:22 +080010994/**
10995 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
10996 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
10997 */
10998TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
10999 // Down on second window
11000 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11001 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
11002 {150, 50}))
11003 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11004
11005 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
11006 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
11007
11008 // Down on first window
11009 const MotionEvent secondFingerDownEvent =
11010 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11011 .displayId(ADISPLAY_ID_DEFAULT)
11012 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
11013 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
11014 .build();
11015 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11016 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
11017 InputEventInjectionSync::WAIT_FOR_RESULT))
11018 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11019 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
11020 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
11021 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
11022
11023 // Start drag on first window
11024 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
11025
11026 // Trigger cancel
11027 mDispatcher->cancelCurrentTouch();
11028 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
Prabir Pradhan65455c72024-02-13 21:46:41 +000011029 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT,
11030 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE));
Linnan Li5af92f92023-07-14 14:36:22 +080011031 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
11032
11033 ASSERT_TRUE(mDispatcher->waitForIdle());
11034 // The D&D finished with nullptr
11035 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
11036
11037 // Remove drag window
11038 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
11039
11040 // Inject a simple gesture, ensure dispatcher not crashed
11041 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11042 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
11043 PointF{50, 50}))
11044 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11045 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
11046
11047 const MotionEvent moveEvent =
11048 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
11049 .displayId(ADISPLAY_ID_DEFAULT)
11050 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11051 .build();
11052 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11053 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
11054 InputEventInjectionSync::WAIT_FOR_RESULT))
11055 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11056 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
11057
11058 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11059 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
11060 {50, 50}))
11061 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11062 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
11063}
11064
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000011065TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
11066 // Start hovering over the window.
11067 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11068 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
11069 ADISPLAY_ID_DEFAULT, {50, 50}));
11070
11071 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
11072 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
11073
11074 ASSERT_FALSE(startDrag(/*sendDown=*/false))
11075 << "Drag and drop should not work with a hovering pointer";
11076}
11077
Vishnu Nair062a8672021-09-03 16:07:44 -070011078class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
11079
11080TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
11081 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011082 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
11083 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011084 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011085 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
11086 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011087 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011088 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011089 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011090
11091 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000011092 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011093 window->assertNoEvents();
11094
Prabir Pradhan678438e2023-04-13 19:32:51 +000011095 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11096 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070011097 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
11098 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080011099 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070011100 window->assertNoEvents();
11101
11102 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011103 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011104 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011105
Prabir Pradhan678438e2023-04-13 19:32:51 +000011106 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011107 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
11108
Prabir Pradhan678438e2023-04-13 19:32:51 +000011109 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11110 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011111 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11112 window->assertNoEvents();
11113}
11114
11115TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
11116 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
11117 std::make_shared<FakeApplicationHandle>();
11118 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011119 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
11120 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070011121 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011122 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011123 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070011124 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011125 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
11126 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011127 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011128 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070011129 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
11130 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011131 mDispatcher->onWindowInfosChanged(
11132 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011133 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011134 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011135
11136 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000011137 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011138 window->assertNoEvents();
11139
Prabir Pradhan678438e2023-04-13 19:32:51 +000011140 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11141 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070011142 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
11143 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011144 window->assertNoEvents();
11145
11146 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011147 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011148 mDispatcher->onWindowInfosChanged(
11149 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011150
Prabir Pradhan678438e2023-04-13 19:32:51 +000011151 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011152 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
11153
Prabir Pradhan678438e2023-04-13 19:32:51 +000011154 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11155 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011156 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
11157 window->assertNoEvents();
11158}
11159
11160TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
11161 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
11162 std::make_shared<FakeApplicationHandle>();
11163 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011164 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
11165 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070011166 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011167 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011168 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070011169 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011170 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
11171 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011172 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011173 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070011174 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
11175 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011176 mDispatcher->onWindowInfosChanged(
11177 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011178 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011179 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011180
11181 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000011182 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011183 window->assertNoEvents();
11184
Prabir Pradhan678438e2023-04-13 19:32:51 +000011185 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11186 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070011187 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
11188 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011189 window->assertNoEvents();
11190
11191 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011192 mDispatcher->onWindowInfosChanged(
11193 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011194
Prabir Pradhan678438e2023-04-13 19:32:51 +000011195 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011196 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
11197
Prabir Pradhan678438e2023-04-13 19:32:51 +000011198 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11199 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011200 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11201 window->assertNoEvents();
11202}
11203
Antonio Kantekf16f2832021-09-28 04:39:20 +000011204class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
11205protected:
11206 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000011207 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000011208 sp<FakeWindowHandle> mWindow;
11209 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000011210 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000011211
11212 void SetUp() override {
11213 InputDispatcherTest::SetUp();
11214
11215 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000011216 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011217 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011218 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011219 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011220 mSecondWindow =
11221 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011222 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000011223 mThirdWindow =
11224 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
11225 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
11226 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011227
11228 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011229 mDispatcher->onWindowInfosChanged(
11230 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
11231 {},
11232 0,
11233 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000011234 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011235 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011236
Antonio Kantek15beb512022-06-13 22:35:41 +000011237 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000011238 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000011239 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070011240 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
11241 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000011242 mThirdWindow->assertNoEvents();
11243 }
11244
11245 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
11246 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000011247 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000011248 SECOND_DISPLAY_ID)) {
11249 mWindow->assertNoEvents();
11250 mSecondWindow->assertNoEvents();
11251 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070011252 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000011253 }
11254
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011255 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000011256 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070011257 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
11258 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000011259 mWindow->consumeTouchModeEvent(inTouchMode);
11260 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000011261 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000011262 }
11263};
11264
Antonio Kantek26defcf2022-02-08 01:12:27 +000011265TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080011266 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000011267 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
11268 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011269 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011270}
11271
Antonio Kantek26defcf2022-02-08 01:12:27 +000011272TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
11273 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011274 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011275 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011276 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011277 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000011278 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -070011279 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000011280 mWindow->assertNoEvents();
11281 mSecondWindow->assertNoEvents();
11282}
11283
11284TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
11285 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011286 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011287 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011288 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000011289 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000011290 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011291}
11292
Antonio Kantekf16f2832021-09-28 04:39:20 +000011293TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080011294 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000011295 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
11296 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011297 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000011298 mWindow->assertNoEvents();
11299 mSecondWindow->assertNoEvents();
11300}
11301
Antonio Kantek15beb512022-06-13 22:35:41 +000011302TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
11303 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
11304 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
11305 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011306 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000011307 mWindow->assertNoEvents();
11308 mSecondWindow->assertNoEvents();
11309 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
11310}
11311
Antonio Kantek48710e42022-03-24 14:19:30 -070011312TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
11313 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011314 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11315 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070011316 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11317 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
11318
11319 // Then remove focus.
11320 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011321 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070011322
11323 // Assert that caller can switch touch mode by owning one of the last interacted window.
11324 const WindowInfo& windowInfo = *mWindow->getInfo();
11325 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
11326 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011327 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070011328}
11329
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011330class InputDispatcherSpyWindowTest : public InputDispatcherTest {
11331public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011332 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011333 std::shared_ptr<FakeApplicationHandle> application =
11334 std::make_shared<FakeApplicationHandle>();
11335 std::string name = "Fake Spy ";
11336 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011337 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
11338 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011339 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011340 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011341 return spy;
11342 }
11343
11344 sp<FakeWindowHandle> createForeground() {
11345 std::shared_ptr<FakeApplicationHandle> application =
11346 std::make_shared<FakeApplicationHandle>();
11347 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011348 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
11349 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011350 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011351 return window;
11352 }
11353
11354private:
11355 int mSpyCount{0};
11356};
11357
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011358using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011359/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011360 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
11361 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011362TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070011363 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011364 ScopedSilentDeath _silentDeath;
11365
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011366 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011367 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011368 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011369 ".* not a trusted overlay");
11370}
11371
11372/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011373 * Input injection into a display with a spy window but no foreground windows should succeed.
11374 */
11375TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011376 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011377 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011378
11379 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011380 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011381 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11382 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11383}
11384
11385/**
11386 * Verify the order in which different input windows receive events. The touched foreground window
11387 * (if there is one) should always receive the event first. When there are multiple spy windows, the
11388 * spy windows will receive the event according to their Z-order, where the top-most spy window will
11389 * receive events before ones belows it.
11390 *
11391 * Here, we set up a scenario with four windows in the following Z order from the top:
11392 * spy1, spy2, window, spy3.
11393 * We then inject an event and verify that the foreground "window" receives it first, followed by
11394 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
11395 * window.
11396 */
11397TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
11398 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011399 auto spy1 = createSpy();
11400 auto spy2 = createSpy();
11401 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011402 mDispatcher->onWindowInfosChanged(
11403 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011404 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
11405 const size_t numChannels = channels.size();
11406
Michael Wright8e9a8562022-02-09 13:44:29 +000011407 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011408 if (!epollFd.ok()) {
11409 FAIL() << "Failed to create epoll fd";
11410 }
11411
11412 for (size_t i = 0; i < numChannels; i++) {
11413 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
11414 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
11415 FAIL() << "Failed to add fd to epoll";
11416 }
11417 }
11418
11419 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011420 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011421 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11422
11423 std::vector<size_t> eventOrder;
11424 std::vector<struct epoll_event> events(numChannels);
11425 for (;;) {
11426 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
11427 (100ms).count());
11428 if (nFds < 0) {
11429 FAIL() << "Failed to call epoll_wait";
11430 }
11431 if (nFds == 0) {
11432 break; // epoll_wait timed out
11433 }
11434 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070011435 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070011436 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011437 channels[i]->consumeMotionDown();
11438 }
11439 }
11440
11441 // Verify the order in which the events were received.
11442 EXPECT_EQ(3u, eventOrder.size());
11443 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
11444 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
11445 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
11446}
11447
11448/**
11449 * A spy window using the NOT_TOUCHABLE flag does not receive events.
11450 */
11451TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
11452 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011453 auto spy = createSpy();
11454 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011455 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011456
11457 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011458 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011459 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11460 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11461 spy->assertNoEvents();
11462}
11463
11464/**
11465 * A spy window will only receive gestures that originate within its touchable region. Gestures that
11466 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
11467 * to the window.
11468 */
11469TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
11470 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011471 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011472 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011473 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011474
11475 // Inject an event outside the spy window's touchable region.
11476 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011477 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011478 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11479 window->consumeMotionDown();
11480 spy->assertNoEvents();
11481 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011482 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011483 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11484 window->consumeMotionUp();
11485 spy->assertNoEvents();
11486
11487 // Inject an event inside the spy window's touchable region.
11488 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011489 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011490 {5, 10}))
11491 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11492 window->consumeMotionDown();
11493 spy->consumeMotionDown();
11494}
11495
11496/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011497 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011498 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011499 */
11500TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
11501 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011502 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011503 auto spy = createSpy();
11504 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011505 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011506 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011507 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011508
11509 // Inject an event outside the spy window's frame and touchable region.
11510 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011511 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011512 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011513 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11514 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011515 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011516}
11517
11518/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011519 * Even when a spy window spans over multiple foreground windows, the spy should receive all
11520 * pointers that are down within its bounds.
11521 */
11522TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
11523 auto windowLeft = createForeground();
11524 windowLeft->setFrame({0, 0, 100, 200});
11525 auto windowRight = createForeground();
11526 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011527 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011528 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011529 mDispatcher->onWindowInfosChanged(
11530 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011531
11532 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011533 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011534 {50, 50}))
11535 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11536 windowLeft->consumeMotionDown();
11537 spy->consumeMotionDown();
11538
11539 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011540 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011541 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011542 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11543 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011544 .build();
11545 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011546 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011547 InputEventInjectionSync::WAIT_FOR_RESULT))
11548 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11549 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000011550 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011551}
11552
11553/**
11554 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
11555 * the spy should receive the second pointer with ACTION_DOWN.
11556 */
11557TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
11558 auto window = createForeground();
11559 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011560 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011561 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011562 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011563
11564 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011565 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011566 {50, 50}))
11567 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11568 window->consumeMotionDown();
11569 spyRight->assertNoEvents();
11570
11571 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011572 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011573 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011574 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11575 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011576 .build();
11577 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011578 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011579 InputEventInjectionSync::WAIT_FOR_RESULT))
11580 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000011581 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011582 spyRight->consumeMotionDown();
11583}
11584
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011585/**
11586 * The spy window should not be able to affect whether or not touches are split. Only the foreground
11587 * windows should be allowed to control split touch.
11588 */
11589TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080011590 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011591 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011592 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080011593 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011594
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011595 auto window = createForeground();
11596 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011597
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011598 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011599
11600 // First finger down, no window touched.
11601 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011602 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011603 {100, 200}))
11604 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11605 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11606 window->assertNoEvents();
11607
11608 // Second finger down on window, the window should receive touch down.
11609 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011610 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011611 .displayId(ADISPLAY_ID_DEFAULT)
11612 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011613 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11614 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011615 .build();
11616 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011617 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011618 InputEventInjectionSync::WAIT_FOR_RESULT))
11619 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11620
11621 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000011622 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011623}
11624
11625/**
11626 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
11627 * do not receive key events.
11628 */
11629TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011630 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011631 spy->setFocusable(false);
11632
11633 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011634 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011635 setFocusedWindow(window);
11636 window->consumeFocusEvent(true);
11637
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011638 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011639 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11640 window->consumeKeyDown(ADISPLAY_ID_NONE);
11641
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011643 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11644 window->consumeKeyUp(ADISPLAY_ID_NONE);
11645
11646 spy->assertNoEvents();
11647}
11648
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011649using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
11650
11651/**
11652 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
11653 * are currently sent to any other windows - including other spy windows - will also be cancelled.
11654 */
11655TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
11656 auto window = createForeground();
11657 auto spy1 = createSpy();
11658 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011659 mDispatcher->onWindowInfosChanged(
11660 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011661
11662 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011663 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011664 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11665 window->consumeMotionDown();
11666 spy1->consumeMotionDown();
11667 spy2->consumeMotionDown();
11668
11669 // Pilfer pointers from the second spy window.
11670 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
11671 spy2->assertNoEvents();
11672 spy1->consumeMotionCancel();
11673 window->consumeMotionCancel();
11674
11675 // The rest of the gesture should only be sent to the second spy window.
11676 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011677 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011678 ADISPLAY_ID_DEFAULT))
11679 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11680 spy2->consumeMotionMove();
11681 spy1->assertNoEvents();
11682 window->assertNoEvents();
11683}
11684
11685/**
11686 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
11687 * in the middle of the gesture.
11688 */
11689TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
11690 auto window = createForeground();
11691 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011692 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011693
11694 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011695 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011696 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11697 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11698 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11699
11700 window->releaseChannel();
11701
11702 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11703
11704 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011705 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011706 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11707 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
11708}
11709
11710/**
11711 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
11712 * the spy, but not to any other windows.
11713 */
11714TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
11715 auto spy = createSpy();
11716 auto window = createForeground();
11717
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011718 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011719
11720 // First finger down on the window and the spy.
11721 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011722 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011723 {100, 200}))
11724 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11725 spy->consumeMotionDown();
11726 window->consumeMotionDown();
11727
11728 // Spy window pilfers the pointers.
11729 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11730 window->consumeMotionCancel();
11731
11732 // Second finger down on the window and spy, but the window should not receive the pointer down.
11733 const MotionEvent secondFingerDownEvent =
11734 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11735 .displayId(ADISPLAY_ID_DEFAULT)
11736 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011737 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11738 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011739 .build();
11740 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011741 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011742 InputEventInjectionSync::WAIT_FOR_RESULT))
11743 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11744
Harry Cutts33476232023-01-30 19:57:29 +000011745 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011746
11747 // Third finger goes down outside all windows, so injection should fail.
11748 const MotionEvent thirdFingerDownEvent =
11749 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11750 .displayId(ADISPLAY_ID_DEFAULT)
11751 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011752 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11753 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
11754 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011755 .build();
11756 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011757 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011758 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080011759 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011760
11761 spy->assertNoEvents();
11762 window->assertNoEvents();
11763}
11764
11765/**
11766 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
11767 */
11768TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
11769 auto spy = createSpy();
11770 spy->setFrame(Rect(0, 0, 100, 100));
11771 auto window = createForeground();
11772 window->setFrame(Rect(0, 0, 200, 200));
11773
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011774 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011775
11776 // First finger down on the window only
11777 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011778 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011779 {150, 150}))
11780 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11781 window->consumeMotionDown();
11782
11783 // Second finger down on the spy and window
11784 const MotionEvent secondFingerDownEvent =
11785 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11786 .displayId(ADISPLAY_ID_DEFAULT)
11787 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011788 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11789 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011790 .build();
11791 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011792 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011793 InputEventInjectionSync::WAIT_FOR_RESULT))
11794 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11795 spy->consumeMotionDown();
11796 window->consumeMotionPointerDown(1);
11797
11798 // Third finger down on the spy and window
11799 const MotionEvent thirdFingerDownEvent =
11800 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11801 .displayId(ADISPLAY_ID_DEFAULT)
11802 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011803 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11804 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
11805 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011806 .build();
11807 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011808 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011809 InputEventInjectionSync::WAIT_FOR_RESULT))
11810 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11811 spy->consumeMotionPointerDown(1);
11812 window->consumeMotionPointerDown(2);
11813
11814 // Spy window pilfers the pointers.
11815 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000011816 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
11817 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011818
11819 spy->assertNoEvents();
11820 window->assertNoEvents();
11821}
11822
11823/**
11824 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
11825 * other windows should be canceled. If this results in the cancellation of all pointers for some
11826 * window, then that window should receive ACTION_CANCEL.
11827 */
11828TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
11829 auto spy = createSpy();
11830 spy->setFrame(Rect(0, 0, 100, 100));
11831 auto window = createForeground();
11832 window->setFrame(Rect(0, 0, 200, 200));
11833
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011834 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011835
11836 // First finger down on both spy and window
11837 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011838 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011839 {10, 10}))
11840 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11841 window->consumeMotionDown();
11842 spy->consumeMotionDown();
11843
11844 // Second finger down on the spy and window
11845 const MotionEvent secondFingerDownEvent =
11846 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11847 .displayId(ADISPLAY_ID_DEFAULT)
11848 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011849 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11850 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011851 .build();
11852 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011853 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011854 InputEventInjectionSync::WAIT_FOR_RESULT))
11855 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11856 spy->consumeMotionPointerDown(1);
11857 window->consumeMotionPointerDown(1);
11858
11859 // Spy window pilfers the pointers.
11860 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11861 window->consumeMotionCancel();
11862
11863 spy->assertNoEvents();
11864 window->assertNoEvents();
11865}
11866
11867/**
11868 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
11869 * be sent to other windows
11870 */
11871TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
11872 auto spy = createSpy();
11873 spy->setFrame(Rect(0, 0, 100, 100));
11874 auto window = createForeground();
11875 window->setFrame(Rect(0, 0, 200, 200));
11876
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011877 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011878
11879 // First finger down on both window and spy
11880 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011881 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011882 {10, 10}))
11883 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11884 window->consumeMotionDown();
11885 spy->consumeMotionDown();
11886
11887 // Spy window pilfers the pointers.
11888 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11889 window->consumeMotionCancel();
11890
11891 // Second finger down on the window only
11892 const MotionEvent secondFingerDownEvent =
11893 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11894 .displayId(ADISPLAY_ID_DEFAULT)
11895 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011896 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11897 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011898 .build();
11899 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011900 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011901 InputEventInjectionSync::WAIT_FOR_RESULT))
11902 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11903 window->consumeMotionDown();
11904 window->assertNoEvents();
11905
11906 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
11907 spy->consumeMotionMove();
11908 spy->assertNoEvents();
11909}
11910
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011911/**
11912 * A window on the left and a window on the right. Also, a spy window that's above all of the
11913 * windows, and spanning both left and right windows.
11914 * Send simultaneous motion streams from two different devices, one to the left window, and another
11915 * to the right window.
11916 * Pilfer from spy window.
11917 * Check that the pilfering only affects the pointers that are actually being received by the spy.
11918 */
11919TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
11920 sp<FakeWindowHandle> spy = createSpy();
11921 spy->setFrame(Rect(0, 0, 200, 200));
11922 sp<FakeWindowHandle> leftWindow = createForeground();
11923 leftWindow->setFrame(Rect(0, 0, 100, 100));
11924
11925 sp<FakeWindowHandle> rightWindow = createForeground();
11926 rightWindow->setFrame(Rect(100, 0, 200, 100));
11927
11928 constexpr int32_t stylusDeviceId = 1;
11929 constexpr int32_t touchDeviceId = 2;
11930
11931 mDispatcher->onWindowInfosChanged(
11932 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
11933
11934 // Stylus down on left window and spy
11935 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
11936 .deviceId(stylusDeviceId)
11937 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
11938 .build());
11939 leftWindow->consumeMotionEvent(
11940 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11941 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11942
11943 // Finger down on right window and spy - but spy already has stylus
11944 mDispatcher->notifyMotion(
11945 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11946 .deviceId(touchDeviceId)
11947 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
11948 .build());
11949 rightWindow->consumeMotionEvent(
11950 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011951 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011952
11953 // Act: pilfer from spy. Spy is currently receiving touch events.
11954 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011955 leftWindow->consumeMotionEvent(
11956 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011957 rightWindow->consumeMotionEvent(
11958 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
11959
11960 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
11961 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
11962 .deviceId(stylusDeviceId)
11963 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
11964 .build());
11965 mDispatcher->notifyMotion(
11966 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
11967 .deviceId(touchDeviceId)
11968 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
11969 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011970 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011971
11972 spy->assertNoEvents();
11973 leftWindow->assertNoEvents();
11974 rightWindow->assertNoEvents();
11975}
11976
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000011977TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
11978 auto window = createForeground();
11979 auto spy = createSpy();
11980 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
11981
11982 mDispatcher->notifyMotion(
11983 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11984 .deviceId(1)
11985 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
11986 .build());
11987 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11988 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11989
11990 // Pilfer pointers from the spy window should fail.
11991 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
11992 spy->assertNoEvents();
11993 window->assertNoEvents();
11994}
11995
Prabir Pradhand65552b2021-10-07 11:23:50 -070011996class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
11997public:
11998 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
11999 std::shared_ptr<FakeApplicationHandle> overlayApplication =
12000 std::make_shared<FakeApplicationHandle>();
12001 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012002 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
12003 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070012004 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012005 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012006 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012007 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070012008 overlay->setTrustedOverlay(true);
12009
12010 std::shared_ptr<FakeApplicationHandle> application =
12011 std::make_shared<FakeApplicationHandle>();
12012 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012013 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
12014 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070012015 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012016 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070012017
12018 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012019 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070012020 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000012021 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070012022 return {std::move(overlay), std::move(window)};
12023 }
12024
12025 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000012026 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070012027 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000012028 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070012029 }
12030
12031 void sendStylusEvent(int32_t action) {
12032 NotifyMotionArgs motionArgs =
12033 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
12034 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012035 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000012036 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070012037 }
12038};
12039
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012040using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
12041
12042TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070012043 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012044 ScopedSilentDeath _silentDeath;
12045
Prabir Pradhand65552b2021-10-07 11:23:50 -070012046 auto [overlay, window] = setupStylusOverlayScenario();
12047 overlay->setTrustedOverlay(false);
12048 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012049 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
12050 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070012051 ".* not a trusted overlay");
12052}
12053
12054TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
12055 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012056 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070012057
12058 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
12059 overlay->consumeMotionDown();
12060 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
12061 overlay->consumeMotionUp();
12062
12063 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
12064 window->consumeMotionDown();
12065 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
12066 window->consumeMotionUp();
12067
12068 overlay->assertNoEvents();
12069 window->assertNoEvents();
12070}
12071
12072TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
12073 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012074 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012075 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070012076
12077 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
12078 overlay->consumeMotionDown();
12079 window->consumeMotionDown();
12080 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
12081 overlay->consumeMotionUp();
12082 window->consumeMotionUp();
12083
12084 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
12085 window->consumeMotionDown();
12086 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
12087 window->consumeMotionUp();
12088
12089 overlay->assertNoEvents();
12090 window->assertNoEvents();
12091}
12092
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000012093/**
12094 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
12095 * The scenario is as follows:
12096 * - The stylus interceptor overlay is configured as a spy window.
12097 * - The stylus interceptor spy receives the start of a new stylus gesture.
12098 * - It pilfers pointers and then configures itself to no longer be a spy.
12099 * - The stylus interceptor continues to receive the rest of the gesture.
12100 */
12101TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
12102 auto [overlay, window] = setupStylusOverlayScenario();
12103 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012104 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000012105
12106 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
12107 overlay->consumeMotionDown();
12108 window->consumeMotionDown();
12109
12110 // The interceptor pilfers the pointers.
12111 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
12112 window->consumeMotionCancel();
12113
12114 // The interceptor configures itself so that it is no longer a spy.
12115 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012116 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000012117
12118 // It continues to receive the rest of the stylus gesture.
12119 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
12120 overlay->consumeMotionMove();
12121 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
12122 overlay->consumeMotionUp();
12123
12124 window->assertNoEvents();
12125}
12126
Prabir Pradhan5735a322022-04-11 17:23:34 +000012127struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012128 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000012129 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000012130 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
12131 std::unique_ptr<InputDispatcher>& mDispatcher;
12132
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012133 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000012134 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
12135
12136 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012137 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000012138 ADISPLAY_ID_DEFAULT, {100, 200},
12139 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
12140 AMOTION_EVENT_INVALID_CURSOR_POSITION},
12141 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
12142 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
12143 }
12144
12145 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012146 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000012147 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000012148 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000012149 mPolicyFlags);
12150 }
12151
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012152 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000012153 std::shared_ptr<FakeApplicationHandle> overlayApplication =
12154 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012155 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
12156 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000012157 window->setOwnerInfo(mPid, mUid);
12158 return window;
12159 }
12160};
12161
12162using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
12163
12164TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012165 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012166 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012167 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012168
12169 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12170 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12171 window->consumeMotionDown();
12172
12173 setFocusedWindow(window);
12174 window->consumeFocusEvent(true);
12175
12176 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12177 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
12178 window->consumeKeyDown(ADISPLAY_ID_NONE);
12179}
12180
12181TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012182 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012183 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012184 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012185
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012186 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012187 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
12188 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12189
12190 setFocusedWindow(window);
12191 window->consumeFocusEvent(true);
12192
12193 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
12194 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
12195 window->assertNoEvents();
12196}
12197
12198TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012199 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012200 auto window = owner.createWindow("Owned window");
12201 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012202 spy->setSpy(true);
12203 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012204 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012205
12206 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12207 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12208 spy->consumeMotionDown();
12209 window->consumeMotionDown();
12210}
12211
12212TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012213 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012214 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012215
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012216 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012217 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012218 randosSpy->setSpy(true);
12219 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012220 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012221
12222 // The event is targeted at owner's window, so injection should succeed, but the spy should
12223 // not receive the event.
12224 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12225 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12226 randosSpy->assertNoEvents();
12227 window->consumeMotionDown();
12228}
12229
12230TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012231 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012232 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012233
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012234 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012235 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012236 randosSpy->setSpy(true);
12237 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012238 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012239
12240 // A user that has injection permission can inject into any window.
12241 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012242 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000012243 ADISPLAY_ID_DEFAULT));
12244 randosSpy->consumeMotionDown();
12245 window->consumeMotionDown();
12246
12247 setFocusedWindow(randosSpy);
12248 randosSpy->consumeFocusEvent(true);
12249
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012250 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000012251 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
12252 window->assertNoEvents();
12253}
12254
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012255TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012256 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012257 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012258
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012259 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012260 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012261 randosWindow->setFrame(Rect{-10, -10, -5, -5});
12262 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012263 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012264
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012265 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000012266 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12267 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12268 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012269 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000012270}
12271
Prabir Pradhan64f21d22023-11-28 21:19:42 +000012272using InputDispatcherPointerInWindowTest = InputDispatcherTest;
12273
12274TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
12275 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12276
12277 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12278 ADISPLAY_ID_DEFAULT);
12279 left->setFrame(Rect(0, 0, 100, 100));
12280 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12281 "Right Window", ADISPLAY_ID_DEFAULT);
12282 right->setFrame(Rect(100, 0, 200, 100));
12283 sp<FakeWindowHandle> spy =
12284 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
12285 spy->setFrame(Rect(0, 0, 200, 100));
12286 spy->setTrustedOverlay(true);
12287 spy->setSpy(true);
12288
12289 mDispatcher->onWindowInfosChanged(
12290 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
12291
12292 // Hover into the left window.
12293 mDispatcher->notifyMotion(
12294 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
12295 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
12296 .build());
12297
12298 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12299 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12300
12301 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12302 /*pointerId=*/0));
12303 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12304 /*pointerId=*/0));
12305 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12306 /*pointerId=*/0));
12307
12308 // Hover move to the right window.
12309 mDispatcher->notifyMotion(
12310 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
12311 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
12312 .build());
12313
12314 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12315 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12316 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
12317
12318 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12319 /*pointerId=*/0));
12320 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12321 /*pointerId=*/0));
12322 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12323 /*pointerId=*/0));
12324
12325 // Stop hovering.
12326 mDispatcher->notifyMotion(
12327 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
12328 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
12329 .build());
12330
12331 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12332 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12333
12334 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12335 /*pointerId=*/0));
12336 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12337 /*pointerId=*/0));
12338 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12339 /*pointerId=*/0));
12340}
12341
12342TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
12343 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12344
12345 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12346 ADISPLAY_ID_DEFAULT);
12347 left->setFrame(Rect(0, 0, 100, 100));
12348 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12349 "Right Window", ADISPLAY_ID_DEFAULT);
12350 right->setFrame(Rect(100, 0, 200, 100));
12351 sp<FakeWindowHandle> spy =
12352 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
12353 spy->setFrame(Rect(0, 0, 200, 100));
12354 spy->setTrustedOverlay(true);
12355 spy->setSpy(true);
12356
12357 mDispatcher->onWindowInfosChanged(
12358 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
12359
12360 // First pointer down on left window.
12361 mDispatcher->notifyMotion(
12362 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12363 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12364 .build());
12365
12366 left->consumeMotionDown();
12367 spy->consumeMotionDown();
12368
12369 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12370 /*pointerId=*/0));
12371 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12372 /*pointerId=*/0));
12373 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12374 /*pointerId=*/0));
12375
12376 // Second pointer down on right window.
12377 mDispatcher->notifyMotion(
12378 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12379 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12380 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
12381 .build());
12382
12383 left->consumeMotionMove();
12384 right->consumeMotionDown();
12385 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
12386
12387 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12388 /*pointerId=*/0));
12389 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12390 /*pointerId=*/0));
12391 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12392 /*pointerId=*/0));
12393 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12394 /*pointerId=*/1));
12395 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12396 /*pointerId=*/1));
12397 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12398 /*pointerId=*/1));
12399
12400 // Second pointer up.
12401 mDispatcher->notifyMotion(
12402 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
12403 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12404 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
12405 .build());
12406
12407 left->consumeMotionMove();
12408 right->consumeMotionUp();
12409 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
12410
12411 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12412 /*pointerId=*/0));
12413 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12414 /*pointerId=*/0));
12415 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12416 /*pointerId=*/0));
12417 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12418 /*pointerId=*/1));
12419 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12420 /*pointerId=*/1));
12421 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12422 /*pointerId=*/1));
12423
12424 // First pointer up.
12425 mDispatcher->notifyMotion(
12426 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
12427 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12428 .build());
12429
12430 left->consumeMotionUp();
12431 spy->consumeMotionUp();
12432
12433 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12434 /*pointerId=*/0));
12435 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12436 /*pointerId=*/0));
12437 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12438 /*pointerId=*/0));
12439}
12440
12441TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
12442 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12443
12444 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12445 ADISPLAY_ID_DEFAULT);
12446 left->setFrame(Rect(0, 0, 100, 100));
12447 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12448 "Right Window", ADISPLAY_ID_DEFAULT);
12449 right->setFrame(Rect(100, 0, 200, 100));
12450
12451 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
12452
12453 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12454 /*pointerId=*/0));
12455 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12456 /*pointerId=*/0));
12457
12458 // Hover move into the window.
12459 mDispatcher->notifyMotion(
12460 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12461 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
12462 .rawXCursorPosition(50)
12463 .rawYCursorPosition(50)
12464 .deviceId(DEVICE_ID)
12465 .build());
12466
12467 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12468
12469 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12470 /*pointerId=*/0));
12471
12472 // Move the mouse with another device. This cancels the hovering pointer from the first device.
12473 mDispatcher->notifyMotion(
12474 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12475 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
12476 .rawXCursorPosition(51)
12477 .rawYCursorPosition(50)
12478 .deviceId(SECOND_DEVICE_ID)
12479 .build());
12480
12481 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12482 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12483
12484 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
12485 // a HOVER_EXIT from the first device.
12486 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12487 /*pointerId=*/0));
12488 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
12489 SECOND_DEVICE_ID,
12490 /*pointerId=*/0));
12491
12492 // Move the mouse outside the window. Document the current behavior, where the window does not
12493 // receive HOVER_EXIT even though the mouse left the window.
12494 mDispatcher->notifyMotion(
12495 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12496 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
12497 .rawXCursorPosition(150)
12498 .rawYCursorPosition(50)
12499 .deviceId(SECOND_DEVICE_ID)
12500 .build());
12501
12502 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12503 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12504 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12505 /*pointerId=*/0));
12506 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
12507 SECOND_DEVICE_ID,
12508 /*pointerId=*/0));
12509}
12510
Garfield Tane84e6f92019-08-29 17:28:41 -070012511} // namespace android::inputdispatcher