blob: 1c37da0482345758bc579a4ce2eb32419645d980 [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{};
158 gui::Pid pid{gui::Pid::INVALID};
159 };
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 Pradhanaeebeb42023-06-13 19:53:03 +0000263 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 Pradhanaeebeb42023-06-13 19:53:03 +0000283 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
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000311 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800312 std::unique_lock lock(mLock);
313 base::ScopedLockAssertion assumeLocked(mLock);
314
315 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
316 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000317 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800318 enabled;
319 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000320 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
321 << ") to be called.";
322 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800323 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000324 auto request = *mPointerCaptureRequest;
325 mPointerCaptureRequest.reset();
326 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800327 }
328
329 void assertSetPointerCaptureNotCalled() {
330 std::unique_lock lock(mLock);
331 base::ScopedLockAssertion assumeLocked(mLock);
332
333 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000334 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800335 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000336 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800337 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000338 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800339 }
340
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -0700341 void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
342 const sp<IBinder>& targetToken) {
343 dispatcher.waitForIdle();
arthurhungf452d0b2021-01-06 00:19:52 +0800344 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800345 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800346 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800347 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800348 }
349
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800350 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
351 std::unique_lock lock(mLock);
352 base::ScopedLockAssertion assumeLocked(mLock);
353 std::optional<sp<IBinder>> receivedToken =
354 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
355 mNotifyInputChannelBroken);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000356 ASSERT_TRUE(receivedToken.has_value()) << "Did not receive the broken channel token";
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800357 ASSERT_EQ(token, *receivedToken);
358 }
359
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800360 /**
361 * Set policy timeout. A value of zero means next key will not be intercepted.
362 */
363 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
364 mInterceptKeyTimeout = timeout;
365 }
366
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -0800367 std::chrono::nanoseconds getKeyWaitingForEventsTimeout() override { return 500ms; }
368
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700369 void setStaleEventTimeout(std::chrono::nanoseconds timeout) { mStaleEventTimeout = timeout; }
370
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800371 void assertUserActivityNotPoked() {
372 std::unique_lock lock(mLock);
373 base::ScopedLockAssertion assumeLocked(mLock);
374
375 std::optional<UserActivityPokeEvent> pokeEvent =
376 getItemFromStorageLockedInterruptible(500ms, mUserActivityPokeEvents, lock,
377 mNotifyUserActivity);
378
379 ASSERT_FALSE(pokeEvent) << "Expected user activity not to have been poked";
Josep del Riob3981622023-04-18 15:49:45 +0000380 }
381
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800382 /**
383 * Asserts that a user activity poke has happened. The earliest recorded poke event will be
384 * cleared after this call.
385 *
386 * If an expected UserActivityPokeEvent is provided, asserts that the given event is the
387 * earliest recorded poke event.
388 */
389 void assertUserActivityPoked(std::optional<UserActivityPokeEvent> expectedPokeEvent = {}) {
390 std::unique_lock lock(mLock);
391 base::ScopedLockAssertion assumeLocked(mLock);
392
393 std::optional<UserActivityPokeEvent> pokeEvent =
394 getItemFromStorageLockedInterruptible(500ms, mUserActivityPokeEvents, lock,
395 mNotifyUserActivity);
396 ASSERT_TRUE(pokeEvent) << "Expected a user poke event";
397
398 if (expectedPokeEvent) {
399 ASSERT_EQ(expectedPokeEvent, *pokeEvent);
400 }
Josep del Riob3981622023-04-18 15:49:45 +0000401 }
402
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000403 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000404 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
405 }
406
407 void assertNotifyDeviceInteractionWasNotCalled() {
408 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
409 }
410
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000411 void setUnhandledKeyHandler(std::function<std::optional<KeyEvent>(const KeyEvent&)> handler) {
412 std::scoped_lock lock(mLock);
413 mUnhandledKeyHandler = handler;
414 }
415
416 void assertUnhandledKeyReported(int32_t keycode) {
417 std::unique_lock lock(mLock);
418 base::ScopedLockAssertion assumeLocked(mLock);
419 std::optional<int32_t> unhandledKeycode =
420 getItemFromStorageLockedInterruptible(100ms, mReportedUnhandledKeycodes, lock,
421 mNotifyUnhandledKey);
422 ASSERT_TRUE(unhandledKeycode) << "Expected unhandled key to be reported";
423 ASSERT_EQ(unhandledKeycode, keycode);
424 }
425
426 void assertUnhandledKeyNotReported() {
427 std::unique_lock lock(mLock);
428 base::ScopedLockAssertion assumeLocked(mLock);
429 std::optional<int32_t> unhandledKeycode =
430 getItemFromStorageLockedInterruptible(10ms, mReportedUnhandledKeycodes, lock,
431 mNotifyUnhandledKey);
432 ASSERT_FALSE(unhandledKeycode) << "Expected unhandled key NOT to be reported";
433 }
434
Michael Wrightd02c5b62014-02-10 15:10:22 -0800435private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700436 std::mutex mLock;
437 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
438 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
439 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
440 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800441
Prabir Pradhan99987712020-11-10 18:43:05 -0800442 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000443
444 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800445
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700446 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700447 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800448 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
449 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700450 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800451 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
452 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700453
arthurhungf452d0b2021-01-06 00:19:52 +0800454 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800455 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800456
457 std::condition_variable mNotifyUserActivity;
458 std::queue<UserActivityPokeEvent> mUserActivityPokeEvents;
arthurhungf452d0b2021-01-06 00:19:52 +0800459
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800460 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
461
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700462 std::chrono::nanoseconds mStaleEventTimeout = 1000ms;
463
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000464 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000465
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000466 std::condition_variable mNotifyUnhandledKey;
467 std::queue<int32_t> mReportedUnhandledKeycodes GUARDED_BY(mLock);
468 std::function<std::optional<KeyEvent>(const KeyEvent&)> mUnhandledKeyHandler GUARDED_BY(mLock);
469
Prabir Pradhanedd96402022-02-15 01:46:16 -0800470 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
471 // for a specific container to become non-empty. When the container is non-empty, return the
472 // first entry from the container and erase it.
473 template <class T>
474 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
475 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
476 // If there is an ANR, Dispatcher won't be idle because there are still events
477 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
478 // before checking if ANR was called.
479 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
480 // to provide it some time to act. 100ms seems reasonable.
481 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
482 const std::chrono::time_point start = std::chrono::steady_clock::now();
483 std::optional<T> token =
484 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
485 if (!token.has_value()) {
486 ADD_FAILURE() << "Did not receive the ANR callback";
487 return {};
488 }
489
490 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
491 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
492 // the dispatcher started counting before this function was called
493 if (std::chrono::abs(timeout - waited) > 100ms) {
494 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
495 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
496 << "ms, but waited "
497 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
498 << "ms instead";
499 }
500 return *token;
501 }
502
503 template <class T>
504 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
505 std::queue<T>& storage,
506 std::unique_lock<std::mutex>& lock,
507 std::condition_variable& condition)
508 REQUIRES(mLock) {
509 condition.wait_for(lock, timeout,
510 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
511 if (storage.empty()) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800512 return std::nullopt;
513 }
514 T item = storage.front();
515 storage.pop();
516 return std::make_optional(item);
517 }
518
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600519 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700520 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800521 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800522 }
523
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000524 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800525 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700526 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800527 ASSERT_TRUE(pid.has_value());
528 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700529 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500530 }
531
Prabir Pradhanedd96402022-02-15 01:46:16 -0800532 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000533 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500534 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800535 ASSERT_TRUE(pid.has_value());
536 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500537 mNotifyAnr.notify_all();
538 }
539
540 void notifyNoFocusedWindowAnr(
541 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
542 std::scoped_lock lock(mLock);
543 mAnrApplications.push(applicationHandle);
544 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800545 }
546
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800547 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
548 std::scoped_lock lock(mLock);
549 mBrokenInputChannels.push(connectionToken);
550 mNotifyInputChannelBroken.notify_all();
551 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800552
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600553 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700554
Chris Yef59a2f42020-10-16 12:55:26 -0700555 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
556 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
557 const std::vector<float>& values) override {}
558
559 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
560 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000561
Chris Yefb552902021-02-03 17:18:37 -0800562 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
563
Prabir Pradhana41d2442023-04-20 21:30:40 +0000564 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700565 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000566 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700567 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000568 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
569 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800570 break;
571 }
572
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700573 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000574 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
575 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800576 break;
577 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700578 default: {
579 ADD_FAILURE() << "Should only filter keys or motions";
580 break;
581 }
Jackal Guof9696682018-10-05 12:23:23 +0800582 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800583 return true;
584 }
585
Prabir Pradhana41d2442023-04-20 21:30:40 +0000586 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
587 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800588 // Clear intercept state when we handled the event.
589 mInterceptKeyTimeout = 0ms;
590 }
591 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800592
Yeabkal Wubshit88a90412023-12-21 18:23:04 -0800593 void interceptMotionBeforeQueueing(int32_t, uint32_t, int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800594
Prabir Pradhana41d2442023-04-20 21:30:40 +0000595 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800596 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
597 // Clear intercept state so we could dispatch the event in next wake.
598 mInterceptKeyTimeout = 0ms;
599 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800600 }
601
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000602 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent& event,
Prabir Pradhana41d2442023-04-20 21:30:40 +0000603 uint32_t) override {
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000604 std::scoped_lock lock(mLock);
605 mReportedUnhandledKeycodes.emplace(event.getKeyCode());
606 mNotifyUnhandledKey.notify_all();
607 return mUnhandledKeyHandler != nullptr ? mUnhandledKeyHandler(event) : std::nullopt;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800608 }
609
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600610 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
611 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700612 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800613 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
614 * essentially a passthrough for notifySwitch.
615 */
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000616 mLastNotifySwitch =
617 NotifySwitchArgs(InputEvent::nextId(), when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800618 }
619
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800620 void pokeUserActivity(nsecs_t eventTime, int32_t eventType, int32_t displayId) override {
Josep del Riob3981622023-04-18 15:49:45 +0000621 std::scoped_lock lock(mLock);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800622 mNotifyUserActivity.notify_all();
623 mUserActivityPokeEvents.push({eventTime, eventType, displayId});
Josep del Riob3981622023-04-18 15:49:45 +0000624 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800625
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700626 bool isStaleEvent(nsecs_t currentTime, nsecs_t eventTime) override {
627 return std::chrono::nanoseconds(currentTime - eventTime) >= mStaleEventTimeout;
628 }
629
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600630 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700631 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700632 mOnPointerDownToken = newToken;
633 }
634
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000635 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800636 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000637 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800638 mPointerCaptureChangedCondition.notify_all();
639 }
640
arthurhungf452d0b2021-01-06 00:19:52 +0800641 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
642 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800643 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800644 mDropTargetWindowToken = token;
645 }
646
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000647 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000648 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000649 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
650 }
651
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700652 void assertFilterInputEventWasCalledInternal(
653 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700654 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800655 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700656 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800657 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800658 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800659};
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700660} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800661
Michael Wrightd02c5b62014-02-10 15:10:22 -0800662// --- InputDispatcherTest ---
663
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000664// The trace is a global variable for now, to avoid having to pass it into all of the
665// FakeWindowHandles created throughout the tests.
666// TODO(b/210460522): Update the tests to avoid the need to have the trace be a global variable.
667static std::shared_ptr<VerifyingTrace> gVerifyingTrace = std::make_shared<VerifyingTrace>();
668
Michael Wrightd02c5b62014-02-10 15:10:22 -0800669class InputDispatcherTest : public testing::Test {
670protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000671 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700672 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800673
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000674 void SetUp() override {
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000675 gVerifyingTrace->reset();
Prabir Pradhana41d2442023-04-20 21:30:40 +0000676 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000677 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy,
678 std::make_unique<FakeInputTracingBackend>(
679 gVerifyingTrace));
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700680
Harry Cutts101ee9b2023-07-06 18:04:14 +0000681 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000682 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700683 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800684 }
685
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000686 void TearDown() override {
Prabir Pradhan0eaf1402024-02-05 22:43:04 +0000687 ASSERT_NO_FATAL_FAILURE(gVerifyingTrace->verifyExpectedEventsTraced());
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700688 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000689 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700690 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800691 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700692
693 /**
694 * Used for debugging when writing the test
695 */
696 void dumpDispatcherState() {
697 std::string dump;
698 mDispatcher->dump(dump);
699 std::stringstream ss(dump);
700 std::string to;
701
702 while (std::getline(ss, to, '\n')) {
703 ALOGE("%s", to.c_str());
704 }
705 }
Vishnu Nair958da932020-08-21 17:12:37 -0700706
Chavi Weingarten847e8512023-03-29 00:26:09 +0000707 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700708 FocusRequest request;
709 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000710 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700711 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
712 request.displayId = window->getInfo()->displayId;
713 mDispatcher->setFocusedWindow(request);
714 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800715};
716
Michael Wrightd02c5b62014-02-10 15:10:22 -0800717TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
718 KeyEvent event;
719
720 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800721 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
722 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000723 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600724 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800725 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000726 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000727 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800728 << "Should reject key events with undefined action.";
729
730 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800731 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
732 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600733 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800734 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000735 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000736 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800737 << "Should reject key events with ACTION_MULTIPLE.";
738}
739
740TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
741 MotionEvent event;
742 PointerProperties pointerProperties[MAX_POINTERS + 1];
743 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800744 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800745 pointerProperties[i].clear();
746 pointerProperties[i].id = i;
747 pointerCoords[i].clear();
748 }
749
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800750 // Some constants commonly used below
751 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
752 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
753 constexpr int32_t metaState = AMETA_NONE;
754 constexpr MotionClassification classification = MotionClassification::NONE;
755
chaviw9eaa22c2020-07-01 16:21:27 -0700756 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800757 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800758 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000759 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700760 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700761 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
762 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000763 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800764 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000765 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000766 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800767 << "Should reject motion events with undefined action.";
768
769 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800770 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800771 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
772 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
773 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
774 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000775 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800776 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000777 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000778 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800779 << "Should reject motion events with pointer down index too large.";
780
Garfield Tanfbe732e2020-01-24 11:26:14 -0800781 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700782 AMOTION_EVENT_ACTION_POINTER_DOWN |
783 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700784 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
785 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700786 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000787 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800788 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000789 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000790 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800791 << "Should reject motion events with pointer down index too small.";
792
793 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800794 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800795 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
796 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
797 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
798 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000799 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800800 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000801 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000802 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800803 << "Should reject motion events with pointer up index too large.";
804
Garfield Tanfbe732e2020-01-24 11:26:14 -0800805 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700806 AMOTION_EVENT_ACTION_POINTER_UP |
807 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700808 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
809 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700810 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000811 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800812 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000813 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000814 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800815 << "Should reject motion events with pointer up index too small.";
816
817 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800818 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
819 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700820 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700821 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
822 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000823 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800824 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000825 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000826 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800827 << "Should reject motion events with 0 pointers.";
828
Garfield Tanfbe732e2020-01-24 11:26:14 -0800829 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
830 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700831 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700832 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
833 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000834 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800835 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000836 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000837 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800838 << "Should reject motion events with more than MAX_POINTERS pointers.";
839
840 // Rejects motion events with invalid pointer ids.
841 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800842 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
843 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700844 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700845 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
846 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000847 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800848 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000849 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000850 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800851 << "Should reject motion events with pointer ids less than 0.";
852
853 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800854 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
855 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700856 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700857 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
858 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000859 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800860 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000861 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000862 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800863 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
864
865 // Rejects motion events with duplicate pointer ids.
866 pointerProperties[0].id = 1;
867 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800868 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
869 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700870 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700871 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
872 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000873 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800874 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000875 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000876 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800877 << "Should reject motion events with duplicate pointer ids.";
878}
879
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800880/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
881
882TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
883 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000884 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800885 ASSERT_TRUE(mDispatcher->waitForIdle());
886
887 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
888}
889
890TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000891 NotifySwitchArgs args(InputEvent::nextId(), /*eventTime=*/20, /*policyFlags=*/0,
892 /*switchValues=*/1,
Harry Cutts33476232023-01-30 19:57:29 +0000893 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000894 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800895
896 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
897 args.policyFlags |= POLICY_FLAG_TRUSTED;
898 mFakePolicy->assertNotifySwitchWasCalled(args);
899}
900
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700901namespace {
902
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700903static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700904// Default input dispatching timeout if there is no focused application or paused window
905// from which to determine an appropriate dispatching timeout.
906static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
907 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
908 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800909
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800910class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800911public:
Garfield Tan15601662020-09-22 15:32:38 -0700912 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700913 : mConsumer(std::move(clientChannel)), mName(name) {}
chaviwd1c23182019-12-20 18:44:56 -0800914
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800915 std::unique_ptr<InputEvent> consume(std::chrono::milliseconds timeout, bool handled = false) {
916 auto [consumeSeq, event] = receiveEvent(timeout);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700917 if (!consumeSeq) {
918 return nullptr;
919 }
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000920 finishEvent(*consumeSeq, handled);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800921 return std::move(event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700922 }
923
924 /**
925 * Receive an event without acknowledging it.
926 * Return the sequence number that could later be used to send finished signal.
927 */
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800928 std::pair<std::optional<uint32_t>, std::unique_ptr<InputEvent>> receiveEvent(
929 std::chrono::milliseconds timeout) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800930 uint32_t consumeSeq;
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800931 std::unique_ptr<InputEvent> event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800932
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800933 std::chrono::time_point start = std::chrono::steady_clock::now();
934 status_t status = WOULD_BLOCK;
935 while (status == WOULD_BLOCK) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800936 InputEvent* rawEventPtr = nullptr;
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700937 status = mConsumer.consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800938 &rawEventPtr);
939 event = std::unique_ptr<InputEvent>(rawEventPtr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800940 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700941 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800942 break;
943 }
944 }
945
946 if (status == WOULD_BLOCK) {
947 // Just means there's no event available.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800948 return std::make_pair(std::nullopt, nullptr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800949 }
950
951 if (status != OK) {
952 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800953 return std::make_pair(std::nullopt, nullptr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800954 }
955 if (event == nullptr) {
956 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800957 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800958 return std::make_pair(consumeSeq, std::move(event));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700959 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800960
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700961 /**
962 * To be used together with "receiveEvent" to complete the consumption of an event.
963 */
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000964 void finishEvent(uint32_t consumeSeq, bool handled = true) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700965 const status_t status = mConsumer.sendFinishedSignal(consumeSeq, handled);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700966 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800967 }
968
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000969 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700970 const status_t status = mConsumer.sendTimeline(inputEventId, timeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000971 ASSERT_EQ(OK, status);
972 }
973
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700974 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000975 std::optional<int32_t> expectedDisplayId,
976 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800977 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800978
979 ASSERT_NE(nullptr, event) << mName.c_str()
980 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800981 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700982 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
983 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800984
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000985 if (expectedDisplayId.has_value()) {
986 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
987 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800988
Tiger Huang8664f8c2018-10-11 19:14:35 +0800989 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700990 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800991 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700992 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000993 if (expectedFlags.has_value()) {
994 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
995 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800996 break;
997 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700998 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800999 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -07001000 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001001 if (expectedFlags.has_value()) {
1002 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
1003 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001004 break;
1005 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001006 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001007 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
1008 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001009 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -08001010 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
1011 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001012 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001013 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
1014 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001015 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +08001016 FAIL() << "Use 'consumeDragEvent' for DRAG events";
1017 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001018 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001019 }
1020
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001021 std::unique_ptr<MotionEvent> consumeMotion() {
1022 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001023
1024 if (event == nullptr) {
1025 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
1026 return nullptr;
1027 }
1028
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001029 if (event->getType() != InputEventType::MOTION) {
1030 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001031 return nullptr;
1032 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001033 return std::unique_ptr<MotionEvent>(static_cast<MotionEvent*>(event.release()));
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001034 }
1035
1036 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001037 std::unique_ptr<MotionEvent> motionEvent = consumeMotion();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001038 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1039 ASSERT_THAT(*motionEvent, matcher);
1040 }
1041
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001042 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001043 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001044 ASSERT_NE(nullptr, event) << mName.c_str()
1045 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001046 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1047 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001048
1049 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1050 << mName.c_str() << ": event displayId should always be NONE.";
1051
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001052 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1053 EXPECT_EQ(hasFocus, focusEvent.getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001054 }
1055
Prabir Pradhan99987712020-11-10 18:43:05 -08001056 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001057 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -08001058 ASSERT_NE(nullptr, event) << mName.c_str()
1059 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001060 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1061 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001062
1063 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1064 << mName.c_str() << ": event displayId should always be NONE.";
1065
1066 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1067 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1068 }
1069
arthurhungb89ccb02020-12-30 16:19:01 +08001070 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001071 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +08001072 ASSERT_NE(nullptr, event) << mName.c_str()
1073 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001074 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001075
1076 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1077 << mName.c_str() << ": event displayId should always be NONE.";
1078
1079 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1080 EXPECT_EQ(isExiting, dragEvent.isExiting());
1081 EXPECT_EQ(x, dragEvent.getX());
1082 EXPECT_EQ(y, dragEvent.getY());
1083 }
1084
Antonio Kantekf16f2832021-09-28 04:39:20 +00001085 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001086 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +00001087 ASSERT_NE(nullptr, event) << mName.c_str()
1088 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001089 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1090 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001091
1092 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1093 << mName.c_str() << ": event displayId should always be NONE.";
1094 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1095 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1096 }
1097
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001098 void assertNoEvents(std::chrono::milliseconds timeout) {
1099 std::unique_ptr<InputEvent> event = consume(timeout);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001100 if (event == nullptr) {
1101 return;
1102 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001103 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001104 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001105 ADD_FAILURE() << "Received key event " << keyEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001106 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001107 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001108 ADD_FAILURE() << "Received motion event " << motionEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001109 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001110 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1111 ADD_FAILURE() << "Received focus event, hasFocus = "
1112 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001113 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001114 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1115 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1116 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001117 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001118 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1119 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1120 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001121 }
1122 FAIL() << mName.c_str()
1123 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001124 }
1125
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001126 sp<IBinder> getToken() { return mConsumer.getChannel()->getConnectionToken(); }
chaviwd1c23182019-12-20 18:44:56 -08001127
Siarhei Vishniakou8d660132024-01-11 16:48:44 -08001128 int getChannelFd() { return mConsumer.getChannel()->getFd(); }
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001129
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001130private:
1131 InputConsumer mConsumer;
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001132 DynamicInputEventFactory mEventFactory;
chaviwd1c23182019-12-20 18:44:56 -08001133
1134 std::string mName;
1135};
1136
chaviw3277faf2021-05-19 16:45:23 -05001137class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001138public:
1139 static const int32_t WIDTH = 600;
1140 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001141
Chris Yea209fde2020-07-22 13:54:51 -07001142 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001143 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001144 int32_t displayId, bool createInputChannel = true)
chaviwd1c23182019-12-20 18:44:56 -08001145 : mName(name) {
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001146 sp<IBinder> token;
1147 if (createInputChannel) {
Garfield Tan15601662020-09-22 15:32:38 -07001148 base::Result<std::unique_ptr<InputChannel>> channel =
1149 dispatcher->createInputChannel(name);
1150 token = (*channel)->getConnectionToken();
1151 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001152 }
1153
1154 inputApplicationHandle->updateInfo();
1155 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1156
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001157 mInfo.token = token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001158 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001159 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001160 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001161 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001162 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001163 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001164 mInfo.globalScaleFactor = 1.0;
1165 mInfo.touchableRegion.clear();
1166 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001167 mInfo.ownerPid = WINDOW_PID;
1168 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001169 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001170 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001171 }
1172
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001173 sp<FakeWindowHandle> clone(int32_t displayId) {
1174 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1175 handle->mInfo = mInfo;
1176 handle->mInfo.displayId = displayId;
1177 handle->mInfo.id = sId++;
1178 handle->mInputReceiver = mInputReceiver;
1179 return handle;
1180 }
1181
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001182 void setTouchable(bool touchable) {
1183 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1184 }
chaviwd1c23182019-12-20 18:44:56 -08001185
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001186 void setFocusable(bool focusable) {
1187 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1188 }
1189
1190 void setVisible(bool visible) {
1191 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1192 }
Vishnu Nair958da932020-08-21 17:12:37 -07001193
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001194 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001195 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001196 }
1197
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001198 void setPaused(bool paused) {
1199 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1200 }
1201
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001202 void setPreventSplitting(bool preventSplitting) {
1203 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001204 }
1205
1206 void setSlippery(bool slippery) {
1207 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1208 }
1209
1210 void setWatchOutsideTouch(bool watchOutside) {
1211 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1212 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001213
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001214 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1215
1216 void setInterceptsStylus(bool interceptsStylus) {
1217 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1218 }
1219
1220 void setDropInput(bool dropInput) {
1221 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1222 }
1223
1224 void setDropInputIfObscured(bool dropInputIfObscured) {
1225 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1226 }
1227
1228 void setNoInputChannel(bool noInputChannel) {
1229 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1230 }
1231
Josep del Riob3981622023-04-18 15:49:45 +00001232 void setDisableUserActivity(bool disableUserActivity) {
1233 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1234 }
1235
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07001236 void setGlobalStylusBlocksTouch(bool shouldGlobalStylusBlockTouch) {
1237 mInfo.setInputConfig(WindowInfo::InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH,
1238 shouldGlobalStylusBlockTouch);
1239 }
1240
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001241 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1242
chaviw3277faf2021-05-19 16:45:23 -05001243 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001244
Bernardo Rufino7393d172021-02-26 13:56:11 +00001245 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1246
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001247 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001248 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001249 mInfo.touchableRegion.clear();
1250 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001251
1252 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1253 ui::Transform translate;
1254 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1255 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001256 }
1257
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001258 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1259
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001260 void setIsWallpaper(bool isWallpaper) {
1261 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1262 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001263
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001264 void setDupTouchToWallpaper(bool hasWallpaper) {
1265 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1266 }
chaviwd1c23182019-12-20 18:44:56 -08001267
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001268 void setTrustedOverlay(bool trustedOverlay) {
1269 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1270 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001271
chaviw9eaa22c2020-07-01 16:21:27 -07001272 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1273 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1274 }
1275
1276 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001277
yunho.shinf4a80b82020-11-16 21:13:57 +09001278 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1279
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001280 std::unique_ptr<KeyEvent> consumeKey(bool handled = true) {
1281 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED, handled);
1282 if (event == nullptr) {
1283 ADD_FAILURE() << "No event";
1284 return nullptr;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001285 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001286 if (event->getType() != InputEventType::KEY) {
1287 ADD_FAILURE() << "Instead of key event, got " << event;
1288 return nullptr;
1289 }
1290 return std::unique_ptr<KeyEvent>(static_cast<KeyEvent*>(event.release()));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001291 }
1292
1293 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001294 std::unique_ptr<KeyEvent> keyEvent = consumeKey();
1295 ASSERT_NE(nullptr, keyEvent);
1296 ASSERT_THAT(*keyEvent, matcher);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001297 }
1298
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001299 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001300 consumeKeyEvent(AllOf(WithKeyAction(ACTION_DOWN), WithDisplayId(expectedDisplayId),
1301 WithFlags(expectedFlags)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001302 }
1303
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001304 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001305 consumeKeyEvent(AllOf(WithKeyAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1306 WithFlags(expectedFlags)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001307 }
1308
Svet Ganov5d3bc372020-01-26 23:11:07 -08001309 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001310 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001311 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1312 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001313 }
1314
1315 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001316 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001317 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1318 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001319 }
1320
1321 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001322 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001323 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1324 }
1325
1326 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1327 std::optional<int32_t> expectedFlags = std::nullopt) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001328 consumeMotionEvent(
1329 AllOf(WithMotionAction(ACTION_DOWN),
1330 testing::Conditional(expectedDisplayId.has_value(),
1331 WithDisplayId(*expectedDisplayId), testing::_),
1332 testing::Conditional(expectedFlags.has_value(), WithFlags(*expectedFlags),
1333 testing::_)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001334 }
1335
Svet Ganov5d3bc372020-01-26 23:11:07 -08001336 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001337 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1338 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001339 const int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001340 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001341 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1342 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001343 }
1344
1345 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001346 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001347 const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001348 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001349 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1350 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001351 }
1352
1353 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001354 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001355 consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1356 WithFlags(expectedFlags)));
Michael Wright3a240c42019-12-10 20:53:41 +00001357 }
1358
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001359 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1360 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001361 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE),
1362 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001363 }
1364
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001365 void consumeMotionOutsideWithZeroedCoords() {
1366 consumeMotionEvent(
1367 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE), WithRawCoords(0, 0)));
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001368 }
1369
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001370 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1371 ASSERT_NE(mInputReceiver, nullptr)
1372 << "Cannot consume events from a window with no receiver";
1373 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1374 }
1375
Prabir Pradhan99987712020-11-10 18:43:05 -08001376 void consumeCaptureEvent(bool hasCapture) {
1377 ASSERT_NE(mInputReceiver, nullptr)
1378 << "Cannot consume events from a window with no receiver";
1379 mInputReceiver->consumeCaptureEvent(hasCapture);
1380 }
1381
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001382 std::unique_ptr<MotionEvent> consumeMotionEvent(
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001383 const ::testing::Matcher<MotionEvent>& matcher = testing::_) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001384 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
1385 if (event == nullptr) {
1386 ADD_FAILURE() << "No event";
1387 return nullptr;
Prabir Pradhan5893d362023-11-17 04:30:40 +00001388 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001389 if (event->getType() != InputEventType::MOTION) {
1390 ADD_FAILURE() << "Instead of motion event, got " << *event;
1391 return nullptr;
1392 }
1393 std::unique_ptr<MotionEvent> motionEvent =
1394 std::unique_ptr<MotionEvent>(static_cast<MotionEvent*>(event.release()));
1395 EXPECT_THAT(*motionEvent, matcher);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001396 return motionEvent;
chaviwd1c23182019-12-20 18:44:56 -08001397 }
1398
arthurhungb89ccb02020-12-30 16:19:01 +08001399 void consumeDragEvent(bool isExiting, float x, float y) {
1400 mInputReceiver->consumeDragEvent(isExiting, x, y);
1401 }
1402
Antonio Kantekf16f2832021-09-28 04:39:20 +00001403 void consumeTouchModeEvent(bool inTouchMode) {
1404 ASSERT_NE(mInputReceiver, nullptr)
1405 << "Cannot consume events from a window with no receiver";
1406 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1407 }
1408
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001409 std::pair<std::optional<uint32_t>, std::unique_ptr<InputEvent>> receiveEvent() {
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001410 return receive();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001411 }
1412
1413 void finishEvent(uint32_t sequenceNum) {
1414 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1415 mInputReceiver->finishEvent(sequenceNum);
1416 }
1417
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001418 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1419 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1420 mInputReceiver->sendTimeline(inputEventId, timeline);
1421 }
1422
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001423 void assertNoEvents(std::chrono::milliseconds timeout = CONSUME_TIMEOUT_NO_EVENT_EXPECTED) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001424 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001425 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001426 return; // Can't receive events if the window does not have input channel
1427 }
1428 ASSERT_NE(nullptr, mInputReceiver)
1429 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001430 mInputReceiver->assertNoEvents(timeout);
Arthur Hungb92218b2018-08-14 12:00:21 +08001431 }
1432
chaviwaf87b3e2019-10-01 16:59:28 -07001433 sp<IBinder> getToken() { return mInfo.token; }
1434
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001435 const std::string& getName() { return mName; }
1436
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001437 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001438 mInfo.ownerPid = ownerPid;
1439 mInfo.ownerUid = ownerUid;
1440 }
1441
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001442 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001443
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001444 void destroyReceiver() { mInputReceiver = nullptr; }
1445
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001446 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1447
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001448 // FakeWindowHandle uses this consume method to ensure received events are added to the trace.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001449 std::unique_ptr<InputEvent> consume(std::chrono::milliseconds timeout, bool handled = true) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001450 if (mInputReceiver == nullptr) {
1451 LOG(FATAL) << "Cannot consume event from a window with no input event receiver";
1452 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001453 std::unique_ptr<InputEvent> event = mInputReceiver->consume(timeout, handled);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001454 if (event == nullptr) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001455 ADD_FAILURE() << "Consume failed: no event";
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001456 }
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001457 expectReceivedEventTraced(event);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001458 return event;
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001459 }
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001460
1461private:
1462 FakeWindowHandle(std::string name) : mName(name){};
1463 const std::string mName;
1464 std::shared_ptr<FakeInputReceiver> mInputReceiver;
1465 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
1466 friend class sp<FakeWindowHandle>;
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001467
1468 // FakeWindowHandle uses this receive method to ensure received events are added to the trace.
1469 std::pair<std::optional<uint32_t /*seq*/>, std::unique_ptr<InputEvent>> receive() {
1470 if (mInputReceiver == nullptr) {
1471 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1472 return std::make_pair(std::nullopt, nullptr);
1473 }
1474 auto out = mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1475 const auto& [_, event] = out;
1476 expectReceivedEventTraced(event);
1477 return std::move(out);
1478 }
1479
1480 void expectReceivedEventTraced(const std::unique_ptr<InputEvent>& event) {
1481 if (!event) {
1482 return;
1483 }
1484
1485 switch (event->getType()) {
1486 case InputEventType::KEY: {
1487 gVerifyingTrace->expectKeyDispatchTraced(static_cast<KeyEvent&>(*event));
1488 break;
1489 }
1490 case InputEventType::MOTION: {
1491 gVerifyingTrace->expectMotionDispatchTraced(static_cast<MotionEvent&>(*event));
1492 break;
1493 }
1494 default:
1495 break;
1496 }
1497 }
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001498};
1499
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001500std::atomic<int32_t> FakeWindowHandle::sId{1};
1501
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001502class FakeMonitorReceiver {
1503public:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001504 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId)
1505 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001506
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001507 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001508
1509 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001510 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1511 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001512 }
1513
1514 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001515 const auto [sequenceNum, _] = mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1516 return sequenceNum;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001517 }
1518
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001519 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001520
1521 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001522 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1523 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001524 }
1525
1526 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001527 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1528 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001529 }
1530
1531 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001532 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1533 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001534 }
1535
1536 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001537 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001538 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1539 WithDisplayId(expectedDisplayId),
1540 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1541 }
1542
1543 void consumeMotionPointerDown(int32_t pointerIdx) {
1544 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1545 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001546 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1547 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001548 }
1549
1550 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001551 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001552 }
1553
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001554 std::unique_ptr<MotionEvent> consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001555
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001556 void assertNoEvents() { mInputReceiver.assertNoEvents(CONSUME_TIMEOUT_NO_EVENT_EXPECTED); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001557
1558private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001559 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001560};
1561
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001562static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001563 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001564 int32_t displayId = ADISPLAY_ID_NONE,
1565 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001566 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001567 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001568 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001569 KeyEvent event;
1570 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1571
1572 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001573 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001574 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1575 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001576
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001577 if (!allowKeyRepeat) {
1578 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1579 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001580 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001581 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001582}
1583
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001584static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1585 InputEventInjectionResult result =
1586 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1587 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1588 if (result != InputEventInjectionResult::TIMED_OUT) {
1589 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1590 }
1591}
1592
1593static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001594 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001595 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001596}
1597
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001598// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1599// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1600// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001601static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1602 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001603 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001604 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001605 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001606}
1607
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001608static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001609 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001610 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001611}
1612
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001613static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001614 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001615 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001616 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001617 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001618 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1619 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001620}
1621
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001622static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001623 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1624 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001625 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001626 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1627 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001628 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001629 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001630 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001631 MotionEventBuilder motionBuilder =
1632 MotionEventBuilder(action, source)
1633 .displayId(displayId)
1634 .eventTime(eventTime)
1635 .rawXCursorPosition(cursorPosition.x)
1636 .rawYCursorPosition(cursorPosition.y)
1637 .pointer(
1638 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1639 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1640 motionBuilder.downTime(eventTime);
1641 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001642
1643 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001644 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1645 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001646}
1647
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001648static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1649 int32_t displayId,
1650 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001651 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001652}
1653
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001654static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1655 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001656 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001657 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001658}
1659
Jackal Guof9696682018-10-05 12:23:23 +08001660static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1661 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1662 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001663 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1664 AINPUT_SOURCE_KEYBOARD, displayId, POLICY_FLAG_PASS_TO_USER, action,
1665 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001666
1667 return args;
1668}
1669
Josep del Riob3981622023-04-18 15:49:45 +00001670static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1671 int32_t displayId = ADISPLAY_ID_NONE) {
1672 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1673 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001674 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1675 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C,
1676 AMETA_META_ON, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001677
1678 return args;
1679}
1680
1681static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1682 int32_t displayId = ADISPLAY_ID_NONE) {
1683 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1684 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001685 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1686 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST,
1687 KEY_ASSISTANT, AMETA_NONE, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001688
1689 return args;
1690}
1691
Prabir Pradhan678438e2023-04-13 19:32:51 +00001692[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1693 int32_t displayId,
1694 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001695 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001696 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1697 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1698 }
1699
chaviwd1c23182019-12-20 18:44:56 -08001700 PointerProperties pointerProperties[pointerCount];
1701 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001702
chaviwd1c23182019-12-20 18:44:56 -08001703 for (size_t i = 0; i < pointerCount; i++) {
1704 pointerProperties[i].clear();
1705 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001706 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001707
chaviwd1c23182019-12-20 18:44:56 -08001708 pointerCoords[i].clear();
1709 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1710 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1711 }
Jackal Guof9696682018-10-05 12:23:23 +08001712
1713 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1714 // Define a valid motion event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001715 NotifyMotionArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, source,
1716 displayId, POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0,
1717 /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001718 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001719 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001720 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001721 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001722
1723 return args;
1724}
1725
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001726static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1727 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1728}
1729
chaviwd1c23182019-12-20 18:44:56 -08001730static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1731 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1732}
1733
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001734static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1735 const PointerCaptureRequest& request) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001736 return NotifyPointerCaptureChangedArgs(InputEvent::nextId(), systemTime(SYSTEM_TIME_MONOTONIC),
1737 request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001738}
1739
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001740} // namespace
1741
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001742/**
1743 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1744 * broken channel.
1745 */
1746TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1747 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1748 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001749 sp<FakeWindowHandle>::make(application, mDispatcher,
1750 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001751
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001752 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001753
1754 // Window closes its channel, but the window remains.
1755 window->destroyReceiver();
1756 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1757}
1758
Arthur Hungb92218b2018-08-14 12:00:21 +08001759TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001760 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001761 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1762 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001763
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001764 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001765 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001766 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001767 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001768
1769 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001770 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001771}
1772
Siarhei Vishniakouaeed0da2024-01-09 08:57:13 -08001773using InputDispatcherDeathTest = InputDispatcherTest;
1774
1775/**
1776 * When 'onWindowInfosChanged' arguments contain a duplicate entry for the same window, dispatcher
1777 * should crash.
1778 */
1779TEST_F(InputDispatcherDeathTest, DuplicateWindowInfosAbortDispatcher) {
1780 testing::GTEST_FLAG(death_test_style) = "threadsafe";
1781 ScopedSilentDeath _silentDeath;
1782
1783 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1784 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1785 "Fake Window", ADISPLAY_ID_DEFAULT);
1786 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
1787 {{*window->getInfo(), *window->getInfo()}, {}, 0, 0}),
1788 "Incorrect WindowInfosUpdate provided");
1789}
1790
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001791TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1792 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001793 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1794 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001795
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001796 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001797 // Inject a MotionEvent to an unknown display.
1798 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001799 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001800 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1801
1802 // Window should receive motion event.
1803 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1804}
1805
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001806/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001807 * Calling onWindowInfosChanged once should not cause any issues.
1808 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001809 * called twice.
1810 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001811TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001812 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001813 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1814 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001815 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001816
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001817 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001818 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001819 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001820 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001821 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001822
1823 // Window should receive motion event.
1824 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1825}
1826
1827/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001828 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001829 */
1830TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001831 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001832 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1833 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001834 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001835
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001836 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1837 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001838 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001839 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001840 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001841 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001842
1843 // Window should receive motion event.
1844 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1845}
1846
Arthur Hungb92218b2018-08-14 12:00:21 +08001847// The foreground window should receive the first touch down event.
1848TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001849 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001850 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001851 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001852 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001853 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001854
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001855 mDispatcher->onWindowInfosChanged(
1856 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001857 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001858 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001859 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001860
1861 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001862 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001863 windowSecond->assertNoEvents();
1864}
1865
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001866/**
1867 * Two windows: A top window, and a wallpaper behind the window.
1868 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1869 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001870 * 1. foregroundWindow <-- dup touch to wallpaper
1871 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001872 */
1873TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1874 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1875 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001876 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001877 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001878 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001879 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001880 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001881
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001882 mDispatcher->onWindowInfosChanged(
1883 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001884 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001885 injectMotionEvent(*mDispatcher,
1886 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1887 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
1888 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001889 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1890
1891 // Both foreground window and its wallpaper should receive the touch down
1892 foregroundWindow->consumeMotionDown();
1893 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1894
1895 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001896 injectMotionEvent(*mDispatcher,
1897 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1898 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
1899 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001900 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1901
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001902 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001903 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1904
1905 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001906 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001907 foregroundWindow->consumeMotionCancel();
1908 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1909 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1910}
1911
1912/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001913 * Two fingers down on the window, and lift off the first finger.
1914 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1915 * contains a single pointer.
1916 */
1917TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1918 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1919 sp<FakeWindowHandle> window =
1920 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1921
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001922 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001923 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001924 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1925 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1926 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001927 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001928 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1929 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1930 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1931 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001932 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001933 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1934 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1935 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1936 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001937 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1938 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1939 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1940
1941 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001942 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001943 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1944 window->consumeMotionEvent(
1945 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1946}
1947
1948/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001949 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1950 * with the following differences:
1951 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1952 * clean up the connection.
1953 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1954 * Ensure that there's no crash in the dispatcher.
1955 */
1956TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1957 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1958 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001959 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001960 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001961 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001962 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001963 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001964
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001965 mDispatcher->onWindowInfosChanged(
1966 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001967 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001968 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001969 {100, 200}))
1970 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1971
1972 // Both foreground window and its wallpaper should receive the touch down
1973 foregroundWindow->consumeMotionDown();
1974 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1975
1976 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001977 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001978 ADISPLAY_ID_DEFAULT, {110, 200}))
1979 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1980
1981 foregroundWindow->consumeMotionMove();
1982 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1983
1984 // Wallpaper closes its channel, but the window remains.
1985 wallpaperWindow->destroyReceiver();
1986 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1987
1988 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1989 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001990 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001991 foregroundWindow->consumeMotionCancel();
1992}
1993
Arthur Hungc539dbb2022-12-08 07:45:36 +00001994class ShouldSplitTouchFixture : public InputDispatcherTest,
1995 public ::testing::WithParamInterface<bool> {};
1996INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1997 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001998/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001999 * A single window that receives touch (on top), and a wallpaper window underneath it.
2000 * The top window gets a multitouch gesture.
2001 * Ensure that wallpaper gets the same gesture.
2002 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00002003TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002004 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002005 sp<FakeWindowHandle> foregroundWindow =
2006 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
2007 foregroundWindow->setDupTouchToWallpaper(true);
2008 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002009
2010 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002011 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002012 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002013
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002014 mDispatcher->onWindowInfosChanged(
2015 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002016
2017 // Touch down on top window
2018 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002019 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002020 {100, 100}))
2021 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2022
2023 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00002024 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002025 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2026
2027 // Second finger down on the top window
2028 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002029 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002030 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002031 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2032 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002033 .build();
2034 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002035 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002036 InputEventInjectionSync::WAIT_FOR_RESULT))
2037 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2038
Harry Cutts33476232023-01-30 19:57:29 +00002039 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
2040 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002041 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00002042
2043 const MotionEvent secondFingerUpEvent =
2044 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2045 .displayId(ADISPLAY_ID_DEFAULT)
2046 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002047 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2048 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002049 .build();
2050 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002051 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002052 InputEventInjectionSync::WAIT_FOR_RESULT))
2053 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2054 foregroundWindow->consumeMotionPointerUp(0);
2055 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2056
2057 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002058 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002059 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2060 AINPUT_SOURCE_TOUCHSCREEN)
2061 .displayId(ADISPLAY_ID_DEFAULT)
2062 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00002063 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002064 .x(100)
2065 .y(100))
2066 .build(),
2067 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002068 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2069 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2070 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002071}
2072
2073/**
2074 * Two windows: a window on the left and window on the right.
2075 * A third window, wallpaper, is behind both windows, and spans both top windows.
2076 * The first touch down goes to the left window. A second pointer touches down on the right window.
2077 * The touch is split, so both left and right windows should receive ACTION_DOWN.
2078 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
2079 * ACTION_POINTER_DOWN(1).
2080 */
2081TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
2082 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2083 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002084 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002085 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002086 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002087
2088 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002089 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002090 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002091 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002092
2093 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002094 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002095 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002096 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002097
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002098 mDispatcher->onWindowInfosChanged(
2099 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2100 {},
2101 0,
2102 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002103
2104 // Touch down on left window
2105 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002106 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002107 {100, 100}))
2108 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2109
2110 // Both foreground window and its wallpaper should receive the touch down
2111 leftWindow->consumeMotionDown();
2112 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2113
2114 // Second finger down on the right window
2115 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002116 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002117 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002118 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2119 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002120 .build();
2121 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002122 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002123 InputEventInjectionSync::WAIT_FOR_RESULT))
2124 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2125
2126 leftWindow->consumeMotionMove();
2127 // Since the touch is split, right window gets ACTION_DOWN
2128 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002129 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002130 expectedWallpaperFlags);
2131
2132 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002133 mDispatcher->onWindowInfosChanged(
2134 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002135 leftWindow->consumeMotionCancel();
2136 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2137 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2138
2139 // The pointer that's still down on the right window moves, and goes to the right window only.
2140 // As far as the dispatcher's concerned though, both pointers are still present.
2141 const MotionEvent secondFingerMoveEvent =
2142 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2143 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002144 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2145 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002146 .build();
2147 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002148 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002149 InputEventInjectionSync::WAIT_FOR_RESULT));
2150 rightWindow->consumeMotionMove();
2151
2152 leftWindow->assertNoEvents();
2153 rightWindow->assertNoEvents();
2154 wallpaperWindow->assertNoEvents();
2155}
2156
Arthur Hungc539dbb2022-12-08 07:45:36 +00002157/**
2158 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2159 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2160 * The right window should receive ACTION_DOWN.
2161 */
2162TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002163 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002164 sp<FakeWindowHandle> leftWindow =
2165 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2166 leftWindow->setFrame(Rect(0, 0, 200, 200));
2167 leftWindow->setDupTouchToWallpaper(true);
2168 leftWindow->setSlippery(true);
2169
2170 sp<FakeWindowHandle> rightWindow =
2171 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2172 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002173
2174 sp<FakeWindowHandle> wallpaperWindow =
2175 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2176 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002177
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002178 mDispatcher->onWindowInfosChanged(
2179 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2180 {},
2181 0,
2182 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002183
Arthur Hungc539dbb2022-12-08 07:45:36 +00002184 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002186 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002187 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002188 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002189
2190 // Both foreground window and its wallpaper should receive the touch down
2191 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002192 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2193
Arthur Hungc539dbb2022-12-08 07:45:36 +00002194 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002195 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002196 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002197 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002198 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2199
Arthur Hungc539dbb2022-12-08 07:45:36 +00002200 leftWindow->consumeMotionCancel();
2201 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2202 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002203}
2204
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002205/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002206 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2207 * interactive, it might stop sending this flag.
2208 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2209 * to have a consistent input stream.
2210 *
2211 * Test procedure:
2212 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2213 * DOWN (new gesture).
2214 *
2215 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2216 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2217 *
2218 * We technically just need a single window here, but we are using two windows (spy on top and a
2219 * regular window below) to emulate the actual situation where it happens on the device.
2220 */
2221TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2222 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2223 sp<FakeWindowHandle> spyWindow =
2224 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2225 spyWindow->setFrame(Rect(0, 0, 200, 200));
2226 spyWindow->setTrustedOverlay(true);
2227 spyWindow->setSpy(true);
2228
2229 sp<FakeWindowHandle> window =
2230 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2231 window->setFrame(Rect(0, 0, 200, 200));
2232
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002233 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002234 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002235
2236 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002237 mDispatcher->notifyMotion(
2238 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2239 .deviceId(touchDeviceId)
2240 .policyFlags(DEFAULT_POLICY_FLAGS)
2241 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2242 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002243
Prabir Pradhan678438e2023-04-13 19:32:51 +00002244 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2245 .deviceId(touchDeviceId)
2246 .policyFlags(DEFAULT_POLICY_FLAGS)
2247 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2248 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2249 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002250 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2251 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2252 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2253 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2254
2255 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002256 mDispatcher->notifyMotion(
2257 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2258 .deviceId(touchDeviceId)
2259 .policyFlags(0)
2260 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2261 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2262 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002263 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2264 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2265
2266 // We don't need to reset the device to reproduce the issue, but the reset event typically
2267 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002268 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002269
2270 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002271 mDispatcher->notifyMotion(
2272 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2273 .deviceId(touchDeviceId)
2274 .policyFlags(DEFAULT_POLICY_FLAGS)
2275 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2276 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002277 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2278 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2279
2280 // No more events
2281 spyWindow->assertNoEvents();
2282 window->assertNoEvents();
2283}
2284
2285/**
Linnan Li907ae732023-09-05 17:14:21 +08002286 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
2287 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2288 * interactive, it might stop sending this flag.
2289 * We've already ensured the consistency of the touch event in this case, and we should also ensure
2290 * the consistency of the hover event in this case.
2291 *
2292 * Test procedure:
2293 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
2294 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
2295 *
2296 * We expect to receive two full streams of hover events.
2297 */
2298TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
2299 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2300
2301 sp<FakeWindowHandle> window =
2302 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2303 window->setFrame(Rect(0, 0, 300, 300));
2304
2305 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2306
2307 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2308 .policyFlags(DEFAULT_POLICY_FLAGS)
2309 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2310 .build());
2311 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2312
2313 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2314 .policyFlags(DEFAULT_POLICY_FLAGS)
2315 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2316 .build());
2317 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2318
2319 // Send hover exit without the default policy flags.
2320 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2321 .policyFlags(0)
2322 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2323 .build());
2324
2325 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2326
2327 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
2328 // right event.
2329 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2330 .policyFlags(DEFAULT_POLICY_FLAGS)
2331 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
2332 .build());
2333 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2334
2335 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2336 .policyFlags(DEFAULT_POLICY_FLAGS)
2337 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2338 .build());
2339 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2340
2341 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2342 .policyFlags(DEFAULT_POLICY_FLAGS)
2343 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2344 .build());
2345 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2346}
2347
2348/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002349 * Two windows: a window on the left and a window on the right.
2350 * Mouse is hovered from the right window into the left window.
2351 * Next, we tap on the left window, where the cursor was last seen.
2352 * The second tap is done onto the right window.
2353 * The mouse and tap are from two different devices.
2354 * We technically don't need to set the downtime / eventtime for these events, but setting these
2355 * explicitly helps during debugging.
2356 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2357 * In the buggy implementation, a tap on the right window would cause a crash.
2358 */
2359TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2360 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2361 sp<FakeWindowHandle> leftWindow =
2362 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2363 leftWindow->setFrame(Rect(0, 0, 200, 200));
2364
2365 sp<FakeWindowHandle> rightWindow =
2366 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2367 rightWindow->setFrame(Rect(200, 0, 400, 200));
2368
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002369 mDispatcher->onWindowInfosChanged(
2370 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002371 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2372 // stale.
2373 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2374 const int32_t mouseDeviceId = 6;
2375 const int32_t touchDeviceId = 4;
2376 // Move the cursor from right
2377 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002378 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002379 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2380 AINPUT_SOURCE_MOUSE)
2381 .deviceId(mouseDeviceId)
2382 .downTime(baseTime + 10)
2383 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002384 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002385 .build()));
2386 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2387
2388 // .. to the left window
2389 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002390 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002391 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2392 AINPUT_SOURCE_MOUSE)
2393 .deviceId(mouseDeviceId)
2394 .downTime(baseTime + 10)
2395 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002396 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002397 .build()));
2398 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2399 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2400 // Now tap the left window
2401 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002402 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002403 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2404 AINPUT_SOURCE_TOUCHSCREEN)
2405 .deviceId(touchDeviceId)
2406 .downTime(baseTime + 40)
2407 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002408 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002409 .build()));
2410 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2411 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2412
2413 // release tap
2414 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002415 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002416 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2417 AINPUT_SOURCE_TOUCHSCREEN)
2418 .deviceId(touchDeviceId)
2419 .downTime(baseTime + 40)
2420 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002421 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002422 .build()));
2423 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2424
2425 // Tap the window on the right
2426 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002427 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002428 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2429 AINPUT_SOURCE_TOUCHSCREEN)
2430 .deviceId(touchDeviceId)
2431 .downTime(baseTime + 60)
2432 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002433 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002434 .build()));
2435 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2436
2437 // release tap
2438 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002439 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002440 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2441 AINPUT_SOURCE_TOUCHSCREEN)
2442 .deviceId(touchDeviceId)
2443 .downTime(baseTime + 60)
2444 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002445 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002446 .build()));
2447 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2448
2449 // No more events
2450 leftWindow->assertNoEvents();
2451 rightWindow->assertNoEvents();
2452}
2453
2454/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002455 * Start hovering in a window. While this hover is still active, make another window appear on top.
2456 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2457 * While the top window is present, the hovering is stopped.
2458 * Later, hovering gets resumed again.
2459 * Ensure that new hover gesture is handled correctly.
2460 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2461 * to the window that's currently being hovered over.
2462 */
2463TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2464 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2465 sp<FakeWindowHandle> window =
2466 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2467 window->setFrame(Rect(0, 0, 200, 200));
2468
2469 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002470 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002471
2472 // Start hovering in the window
2473 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2474 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2475 .build());
2476 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2477
2478 // Now, an obscuring window appears!
2479 sp<FakeWindowHandle> obscuringWindow =
2480 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2481 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002482 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002483 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2484 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2485 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2486 obscuringWindow->setNoInputChannel(true);
2487 obscuringWindow->setFocusable(false);
2488 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002489 mDispatcher->onWindowInfosChanged(
2490 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002491
2492 // While this new obscuring window is present, the hovering is stopped
2493 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2494 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2495 .build());
2496 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2497
2498 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002499 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002500
2501 // And a new hover gesture starts.
2502 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2503 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2504 .build());
2505 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2506}
2507
2508/**
2509 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2510 * the obscuring window.
2511 */
2512TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2513 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2514 sp<FakeWindowHandle> window =
2515 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2516 window->setFrame(Rect(0, 0, 200, 200));
2517
2518 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002519 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002520
2521 // Start hovering in the window
2522 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2523 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2524 .build());
2525 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2526
2527 // Now, an obscuring window appears!
2528 sp<FakeWindowHandle> obscuringWindow =
2529 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2530 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002531 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002532 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2533 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2534 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2535 obscuringWindow->setNoInputChannel(true);
2536 obscuringWindow->setFocusable(false);
2537 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002538 mDispatcher->onWindowInfosChanged(
2539 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002540
2541 // While this new obscuring window is present, the hovering continues. The event can't go to the
2542 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2543 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2544 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2545 .build());
2546 obscuringWindow->assertNoEvents();
2547 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2548
2549 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002550 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002551
2552 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2553 // so it should generate a HOVER_ENTER
2554 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2555 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2556 .build());
2557 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2558
2559 // Now the MOVE should be getting dispatched normally
2560 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2561 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2562 .build());
2563 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2564}
2565
2566/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002567 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2568 * events are delivered to the window.
2569 */
2570TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2571 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2572 sp<FakeWindowHandle> window =
2573 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2574 window->setFrame(Rect(0, 0, 200, 200));
2575 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2576
2577 // Start hovering in the window
2578 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2579 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2580 .build());
2581 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2582
2583 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2584 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2585 .build());
2586 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2587
2588 // Scroll with the mouse
2589 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2590 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2591 .build());
2592 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2593}
2594
2595using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2596
2597/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002598 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2599 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002600 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002601TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002602 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2603 sp<FakeWindowHandle> window =
2604 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2605 window->setFrame(Rect(0, 0, 200, 200));
2606
2607 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2608
2609 constexpr int32_t touchDeviceId = 4;
2610 constexpr int32_t stylusDeviceId = 2;
2611
2612 // Stylus down
2613 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2614 .deviceId(stylusDeviceId)
2615 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2616 .build());
2617 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2618
2619 // Touch down
2620 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2621 .deviceId(touchDeviceId)
2622 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2623 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002624
2625 // Touch move
2626 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2627 .deviceId(touchDeviceId)
2628 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2629 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002630 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002631
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002632 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002633 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2634 .deviceId(stylusDeviceId)
2635 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2636 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002637 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2638 WithCoords(101, 111)));
2639
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002640 window->assertNoEvents();
2641}
2642
2643/**
2644 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002645 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002646 * Similar test as above, but with added SPY window.
2647 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002648TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002649 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2650 sp<FakeWindowHandle> window =
2651 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2652 sp<FakeWindowHandle> spyWindow =
2653 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2654 spyWindow->setFrame(Rect(0, 0, 200, 200));
2655 spyWindow->setTrustedOverlay(true);
2656 spyWindow->setSpy(true);
2657 window->setFrame(Rect(0, 0, 200, 200));
2658
2659 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2660
2661 constexpr int32_t touchDeviceId = 4;
2662 constexpr int32_t stylusDeviceId = 2;
2663
2664 // Stylus down
2665 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2666 .deviceId(stylusDeviceId)
2667 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2668 .build());
2669 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2670 spyWindow->consumeMotionEvent(
2671 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2672
2673 // Touch down
2674 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2675 .deviceId(touchDeviceId)
2676 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2677 .build());
2678
2679 // Touch move
2680 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2681 .deviceId(touchDeviceId)
2682 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2683 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002684
2685 // Touch is ignored because stylus is already down
2686
2687 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002688 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2689 .deviceId(stylusDeviceId)
2690 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2691 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002692 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2693 WithCoords(101, 111)));
2694 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2695 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002696
2697 window->assertNoEvents();
2698 spyWindow->assertNoEvents();
2699}
2700
2701/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002702 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002703 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002704 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002705TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002706 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2707 sp<FakeWindowHandle> window =
2708 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2709 window->setFrame(Rect(0, 0, 200, 200));
2710
2711 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2712
2713 constexpr int32_t touchDeviceId = 4;
2714 constexpr int32_t stylusDeviceId = 2;
2715
2716 // Stylus down on the window
2717 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2718 .deviceId(stylusDeviceId)
2719 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2720 .build());
2721 window->consumeMotionEvent(
2722 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2723
2724 // Touch down on window
2725 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2726 .deviceId(touchDeviceId)
2727 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2728 .build());
2729 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2730 .deviceId(touchDeviceId)
2731 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2732 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002733
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002734 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002735
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002736 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002737 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2738 .deviceId(stylusDeviceId)
2739 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2740 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002741 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2742 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002743
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002744 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002745 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2746 .deviceId(touchDeviceId)
2747 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2748 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002749 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002750}
2751
2752/**
2753 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002754 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002755 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002756TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002757 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2758 sp<FakeWindowHandle> window =
2759 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2760 window->setFrame(Rect(0, 0, 200, 200));
2761
2762 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2763
2764 constexpr int32_t touchDeviceId = 4;
2765 constexpr int32_t stylusDeviceId = 2;
2766
2767 // Touch down on window
2768 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2769 .deviceId(touchDeviceId)
2770 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2771 .build());
2772 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2773 .deviceId(touchDeviceId)
2774 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2775 .build());
2776 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2777 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2778
2779 // Stylus hover on the window
2780 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2781 .deviceId(stylusDeviceId)
2782 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2783 .build());
2784 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2785 .deviceId(stylusDeviceId)
2786 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2787 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002788 // Stylus hover movement causes touch to be canceled
2789 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2790 WithCoords(141, 146)));
2791 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2792 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2793 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2794 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002795
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002796 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002797 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2798 .deviceId(touchDeviceId)
2799 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2800 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002801
2802 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002803}
2804
2805/**
2806 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2807 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2808 * become active.
2809 */
2810TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
2811 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2812 sp<FakeWindowHandle> window =
2813 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2814 window->setFrame(Rect(0, 0, 200, 200));
2815
2816 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2817
2818 constexpr int32_t stylusDeviceId1 = 3;
2819 constexpr int32_t stylusDeviceId2 = 5;
2820
2821 // Touch down on window
2822 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2823 .deviceId(stylusDeviceId1)
2824 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2825 .build());
2826 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2827 .deviceId(stylusDeviceId1)
2828 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2829 .build());
2830 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2831 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2832
2833 // Second stylus down
2834 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2835 .deviceId(stylusDeviceId2)
2836 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2837 .build());
2838 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2839 .deviceId(stylusDeviceId2)
2840 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2841 .build());
2842
2843 // First stylus is canceled, second one takes over.
2844 window->consumeMotionEvent(
2845 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2846 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2847 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2848
2849 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2850 .deviceId(stylusDeviceId1)
2851 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2852 .build());
2853 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002854 window->assertNoEvents();
2855}
2856
2857/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002858 * One window. Touch down on the window. Then, stylus down on the window from another device.
2859 * Ensure that is canceled, because stylus down should be preferred over touch.
2860 */
2861TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
2862 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2863 sp<FakeWindowHandle> window =
2864 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2865 window->setFrame(Rect(0, 0, 200, 200));
2866
2867 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2868
2869 constexpr int32_t touchDeviceId = 4;
2870 constexpr int32_t stylusDeviceId = 2;
2871
2872 // Touch down on window
2873 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2874 .deviceId(touchDeviceId)
2875 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2876 .build());
2877 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2878 .deviceId(touchDeviceId)
2879 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2880 .build());
2881 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2882 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2883
2884 // Stylus down on the window
2885 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2886 .deviceId(stylusDeviceId)
2887 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2888 .build());
2889 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2890 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2891
2892 // Subsequent stylus movements are delivered correctly
2893 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2894 .deviceId(stylusDeviceId)
2895 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2896 .build());
2897 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2898 WithCoords(101, 111)));
2899}
2900
2901/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002902 * Two windows: a window on the left and a window on the right.
2903 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2904 * down. Then, on the left window, also place second touch pointer down.
2905 * This test tries to reproduce a crash.
2906 * In the buggy implementation, second pointer down on the left window would cause a crash.
2907 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002908TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002909 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2910 sp<FakeWindowHandle> leftWindow =
2911 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2912 leftWindow->setFrame(Rect(0, 0, 200, 200));
2913
2914 sp<FakeWindowHandle> rightWindow =
2915 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2916 rightWindow->setFrame(Rect(200, 0, 400, 200));
2917
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002918 mDispatcher->onWindowInfosChanged(
2919 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002920
2921 const int32_t touchDeviceId = 4;
2922 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002923
2924 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002925 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2926 .deviceId(mouseDeviceId)
2927 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2928 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002929 leftWindow->consumeMotionEvent(
2930 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2931
2932 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002933 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2934 .deviceId(mouseDeviceId)
2935 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2936 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2937 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002938
2939 leftWindow->consumeMotionEvent(
2940 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2941 leftWindow->consumeMotionEvent(
2942 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2943
Prabir Pradhan678438e2023-04-13 19:32:51 +00002944 mDispatcher->notifyMotion(
2945 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2946 .deviceId(mouseDeviceId)
2947 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2948 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2949 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2950 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002951 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2952
2953 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002954 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2955 .deviceId(touchDeviceId)
2956 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2957 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002958 leftWindow->assertNoEvents();
2959
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002960 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2961
2962 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002963 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2964 .deviceId(touchDeviceId)
2965 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2966 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2967 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002968 // Since this is now a new splittable pointer going down on the left window, and it's coming
2969 // from a different device, the current gesture in the left window (pointer down) should first
2970 // be canceled.
2971 leftWindow->consumeMotionEvent(
2972 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002973 leftWindow->consumeMotionEvent(
2974 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2975 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2976 // current implementation.
2977 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2978 rightWindow->consumeMotionEvent(
2979 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2980
2981 leftWindow->assertNoEvents();
2982 rightWindow->assertNoEvents();
2983}
2984
2985/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002986 * Two windows: a window on the left and a window on the right.
2987 * Mouse is hovered on the left window and stylus is hovered on the right window.
2988 */
2989TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2990 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2991 sp<FakeWindowHandle> leftWindow =
2992 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2993 leftWindow->setFrame(Rect(0, 0, 200, 200));
2994
2995 sp<FakeWindowHandle> rightWindow =
2996 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2997 rightWindow->setFrame(Rect(200, 0, 400, 200));
2998
2999 mDispatcher->onWindowInfosChanged(
3000 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3001
3002 const int32_t stylusDeviceId = 3;
3003 const int32_t mouseDeviceId = 6;
3004
3005 // Start hovering over the left window
3006 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3007 .deviceId(mouseDeviceId)
3008 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
3009 .build());
3010 leftWindow->consumeMotionEvent(
3011 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3012
3013 // Stylus hovered on right window
3014 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3015 .deviceId(stylusDeviceId)
3016 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
3017 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003018 rightWindow->consumeMotionEvent(
3019 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3020
3021 // Subsequent HOVER_MOVE events are dispatched correctly.
3022 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
3023 .deviceId(mouseDeviceId)
3024 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
3025 .build());
3026 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003027 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003028
3029 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3030 .deviceId(stylusDeviceId)
3031 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
3032 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003033 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003034 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003035
3036 leftWindow->assertNoEvents();
3037 rightWindow->assertNoEvents();
3038}
3039
3040/**
3041 * Three windows: a window on the left and a window on the right.
3042 * And a spy window that's positioned above all of them.
3043 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
3044 * Check the stream that's received by the spy.
3045 */
3046TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
3047 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3048
3049 sp<FakeWindowHandle> spyWindow =
3050 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3051 spyWindow->setFrame(Rect(0, 0, 400, 400));
3052 spyWindow->setTrustedOverlay(true);
3053 spyWindow->setSpy(true);
3054
3055 sp<FakeWindowHandle> leftWindow =
3056 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3057 leftWindow->setFrame(Rect(0, 0, 200, 200));
3058
3059 sp<FakeWindowHandle> rightWindow =
3060 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3061
3062 rightWindow->setFrame(Rect(200, 0, 400, 200));
3063
3064 mDispatcher->onWindowInfosChanged(
3065 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3066
3067 const int32_t stylusDeviceId = 1;
3068 const int32_t touchDeviceId = 2;
3069
3070 // Stylus down on the left window
3071 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3072 .deviceId(stylusDeviceId)
3073 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3074 .build());
3075 leftWindow->consumeMotionEvent(
3076 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3077 spyWindow->consumeMotionEvent(
3078 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3079
3080 // Touch down on the right window
3081 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3082 .deviceId(touchDeviceId)
3083 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3084 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003085 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003086 rightWindow->consumeMotionEvent(
3087 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003088
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003089 // Spy window does not receive touch events, because stylus events take precedence, and it
3090 // already has an active stylus gesture.
3091
3092 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003093 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3094 .deviceId(stylusDeviceId)
3095 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3096 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003097 leftWindow->consumeMotionEvent(
3098 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3099 spyWindow->consumeMotionEvent(
3100 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003101
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003102 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003103 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3104 .deviceId(touchDeviceId)
3105 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
3106 .build());
3107 rightWindow->consumeMotionEvent(
3108 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003109
3110 spyWindow->assertNoEvents();
3111 leftWindow->assertNoEvents();
3112 rightWindow->assertNoEvents();
3113}
3114
3115/**
3116 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3117 * both.
3118 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003119 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003120 * At the same time, left and right should be getting independent streams of hovering and touch,
3121 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003122 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003123TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003124 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3125
3126 sp<FakeWindowHandle> spyWindow =
3127 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3128 spyWindow->setFrame(Rect(0, 0, 400, 400));
3129 spyWindow->setTrustedOverlay(true);
3130 spyWindow->setSpy(true);
3131
3132 sp<FakeWindowHandle> leftWindow =
3133 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3134 leftWindow->setFrame(Rect(0, 0, 200, 200));
3135
3136 sp<FakeWindowHandle> rightWindow =
3137 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3138 rightWindow->setFrame(Rect(200, 0, 400, 200));
3139
3140 mDispatcher->onWindowInfosChanged(
3141 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3142
3143 const int32_t stylusDeviceId = 1;
3144 const int32_t touchDeviceId = 2;
3145
3146 // Stylus hover on the left window
3147 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3148 .deviceId(stylusDeviceId)
3149 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3150 .build());
3151 leftWindow->consumeMotionEvent(
3152 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3153 spyWindow->consumeMotionEvent(
3154 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3155
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003156 // Touch down on the right window. Spy doesn't receive this touch because it already has
3157 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003158 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3159 .deviceId(touchDeviceId)
3160 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3161 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003162 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003163 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003164 rightWindow->consumeMotionEvent(
3165 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3166
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003167 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003168 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3169 .deviceId(stylusDeviceId)
3170 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3171 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003172 leftWindow->consumeMotionEvent(
3173 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003174 spyWindow->consumeMotionEvent(
3175 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003176
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003177 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003178 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3179 .deviceId(touchDeviceId)
3180 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3181 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003182 rightWindow->consumeMotionEvent(
3183 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3184
3185 spyWindow->assertNoEvents();
3186 leftWindow->assertNoEvents();
3187 rightWindow->assertNoEvents();
3188}
3189
3190/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003191 * On a single window, use two different devices: mouse and touch.
3192 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3193 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3194 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3195 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3196 * represent a new gesture.
3197 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003198TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003199 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3200 sp<FakeWindowHandle> window =
3201 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3202 window->setFrame(Rect(0, 0, 400, 400));
3203
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003204 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003205
3206 const int32_t touchDeviceId = 4;
3207 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003208
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003209 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003210 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3211 .deviceId(touchDeviceId)
3212 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3213 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003214 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003215 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3216 .deviceId(touchDeviceId)
3217 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3218 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3219 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003220 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003221 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3222 .deviceId(touchDeviceId)
3223 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3224 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3225 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003226 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3227 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3228 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3229
3230 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003231 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3232 .deviceId(mouseDeviceId)
3233 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3234 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3235 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003236
3237 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003238 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003239 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3240
Prabir Pradhan678438e2023-04-13 19:32:51 +00003241 mDispatcher->notifyMotion(
3242 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3243 .deviceId(mouseDeviceId)
3244 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3245 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3246 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3247 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003248 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3249
3250 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003251 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3252 .deviceId(touchDeviceId)
3253 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3254 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3255 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003256 // Since we already canceled this touch gesture, it will be ignored until a completely new
3257 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3258 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3259 // However, mouse movements should continue to work.
3260 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3261 .deviceId(mouseDeviceId)
3262 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3263 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3264 .build());
3265 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3266
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003267 window->assertNoEvents();
3268}
3269
3270/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003271 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3272 * the injected event.
3273 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003274TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003275 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3276 sp<FakeWindowHandle> window =
3277 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3278 window->setFrame(Rect(0, 0, 400, 400));
3279
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003280 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003281
3282 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003283 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3284 // completion.
3285 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003286 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003287 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3288 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003289 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003290 .build()));
3291 window->consumeMotionEvent(
3292 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3293
3294 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3295 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003296 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3297 .deviceId(touchDeviceId)
3298 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3299 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003300
3301 window->consumeMotionEvent(
3302 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3303 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3304}
3305
3306/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003307 * This test is similar to the test above, but the sequence of injected events is different.
3308 *
3309 * Two windows: a window on the left and a window on the right.
3310 * Mouse is hovered over the left window.
3311 * Next, we tap on the left window, where the cursor was last seen.
3312 *
3313 * After that, we inject one finger down onto the right window, and then a second finger down onto
3314 * the left window.
3315 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3316 * window (first), and then another on the left window (second).
3317 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3318 * In the buggy implementation, second finger down on the left window would cause a crash.
3319 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003320TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003321 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3322 sp<FakeWindowHandle> leftWindow =
3323 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3324 leftWindow->setFrame(Rect(0, 0, 200, 200));
3325
3326 sp<FakeWindowHandle> rightWindow =
3327 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3328 rightWindow->setFrame(Rect(200, 0, 400, 200));
3329
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003330 mDispatcher->onWindowInfosChanged(
3331 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003332
3333 const int32_t mouseDeviceId = 6;
3334 const int32_t touchDeviceId = 4;
3335 // Hover over the left window. Keep the cursor there.
3336 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003337 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003338 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3339 AINPUT_SOURCE_MOUSE)
3340 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003341 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003342 .build()));
3343 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3344
3345 // Tap on left window
3346 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003347 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003348 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3349 AINPUT_SOURCE_TOUCHSCREEN)
3350 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003351 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003352 .build()));
3353
3354 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003355 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003356 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3357 AINPUT_SOURCE_TOUCHSCREEN)
3358 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003359 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003360 .build()));
3361 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3362 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3363 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3364
3365 // First finger down on right window
3366 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003367 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003368 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3369 AINPUT_SOURCE_TOUCHSCREEN)
3370 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003371 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003372 .build()));
3373 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3374
3375 // Second finger down on the left window
3376 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003377 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003378 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3379 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003380 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3381 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003382 .build()));
3383 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3384 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3385
3386 // No more events
3387 leftWindow->assertNoEvents();
3388 rightWindow->assertNoEvents();
3389}
3390
3391/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003392 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3393 * While the touch is down, new hover events from the stylus device should be ignored. After the
3394 * touch is gone, stylus hovering should start working again.
3395 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003396TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003397 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3398 sp<FakeWindowHandle> window =
3399 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3400 window->setFrame(Rect(0, 0, 200, 200));
3401
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003402 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003403
3404 const int32_t stylusDeviceId = 5;
3405 const int32_t touchDeviceId = 4;
3406 // Start hovering with stylus
3407 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003408 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003409 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003410 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003411 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003412 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003413 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003414
3415 // Finger down on the window
3416 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003417 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003418 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003419 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003420 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003421 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003422 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003423
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003424 // Continue hovering with stylus.
3425 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003426 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003427 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3428 AINPUT_SOURCE_STYLUS)
3429 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003430 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003431 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003432 // Hovers continue to work
3433 window->consumeMotionEvent(
3434 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003435
3436 // Lift up the finger
3437 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003438 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003439 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3440 AINPUT_SOURCE_TOUCHSCREEN)
3441 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003442 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003443 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003444
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003445 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003446 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003447 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3448 AINPUT_SOURCE_STYLUS)
3449 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003450 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003451 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003452 window->consumeMotionEvent(
3453 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003454 window->assertNoEvents();
3455}
3456
3457/**
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003458 * If stylus is down anywhere on the screen, then touches should not be delivered to windows that
3459 * have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3460 *
3461 * Two windows: one on the left and one on the right.
3462 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3463 * Stylus down on the left window, and then touch down on the right window.
3464 * Check that the right window doesn't get touches while the stylus is down on the left window.
3465 */
3466TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusDownBlocksTouch) {
3467 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3468 sp<FakeWindowHandle> leftWindow =
3469 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3470 ADISPLAY_ID_DEFAULT);
3471 leftWindow->setFrame(Rect(0, 0, 100, 100));
3472
3473 sp<FakeWindowHandle> sbtRightWindow =
3474 sp<FakeWindowHandle>::make(application, mDispatcher,
3475 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3476 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3477 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3478
3479 mDispatcher->onWindowInfosChanged(
3480 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3481
3482 const int32_t stylusDeviceId = 5;
3483 const int32_t touchDeviceId = 4;
3484
3485 // Stylus down in the left window
3486 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3487 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3488 .deviceId(stylusDeviceId)
3489 .build());
3490 leftWindow->consumeMotionEvent(
3491 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3492
3493 // Finger tap on the right window
3494 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3495 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3496 .deviceId(touchDeviceId)
3497 .build());
3498 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3499 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3500 .deviceId(touchDeviceId)
3501 .build());
3502
3503 // The touch should be blocked, because stylus is down somewhere else on screen!
3504 sbtRightWindow->assertNoEvents();
3505
3506 // Continue stylus motion, and ensure it's not impacted.
3507 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3508 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3509 .deviceId(stylusDeviceId)
3510 .build());
3511 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3512 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3513 .deviceId(stylusDeviceId)
3514 .build());
3515 leftWindow->consumeMotionEvent(
3516 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3517 leftWindow->consumeMotionEvent(
3518 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(stylusDeviceId)));
3519
3520 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3521 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3522 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3523 .deviceId(touchDeviceId)
3524 .build());
3525 sbtRightWindow->consumeMotionEvent(
3526 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3527}
3528
3529/**
3530 * If stylus is hovering anywhere on the screen, then touches should not be delivered to windows
3531 * that have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3532 *
3533 * Two windows: one on the left and one on the right.
3534 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3535 * Stylus hover on the left window, and then touch down on the right window.
3536 * Check that the right window doesn't get touches while the stylus is hovering on the left window.
3537 */
3538TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusHoverBlocksTouch) {
3539 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3540 sp<FakeWindowHandle> leftWindow =
3541 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3542 ADISPLAY_ID_DEFAULT);
3543 leftWindow->setFrame(Rect(0, 0, 100, 100));
3544
3545 sp<FakeWindowHandle> sbtRightWindow =
3546 sp<FakeWindowHandle>::make(application, mDispatcher,
3547 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3548 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3549 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3550
3551 mDispatcher->onWindowInfosChanged(
3552 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3553
3554 const int32_t stylusDeviceId = 5;
3555 const int32_t touchDeviceId = 4;
3556
3557 // Stylus hover in the left window
3558 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3559 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3560 .deviceId(stylusDeviceId)
3561 .build());
3562 leftWindow->consumeMotionEvent(
3563 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3564
3565 // Finger tap on the right window
3566 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3567 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3568 .deviceId(touchDeviceId)
3569 .build());
3570 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3571 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3572 .deviceId(touchDeviceId)
3573 .build());
3574
3575 // The touch should be blocked, because stylus is hovering somewhere else on screen!
3576 sbtRightWindow->assertNoEvents();
3577
3578 // Continue stylus motion, and ensure it's not impacted.
3579 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3580 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3581 .deviceId(stylusDeviceId)
3582 .build());
3583 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3584 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3585 .deviceId(stylusDeviceId)
3586 .build());
3587 leftWindow->consumeMotionEvent(
3588 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3589 leftWindow->consumeMotionEvent(
3590 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3591
3592 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3593 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3594 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3595 .deviceId(touchDeviceId)
3596 .build());
3597 sbtRightWindow->consumeMotionEvent(
3598 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3599}
3600
3601/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003602 * A spy window above a window with no input channel.
3603 * Start hovering with a stylus device, and then tap with it.
3604 * Ensure spy window receives the entire sequence.
3605 */
3606TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3607 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3608 sp<FakeWindowHandle> spyWindow =
3609 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3610 spyWindow->setFrame(Rect(0, 0, 200, 200));
3611 spyWindow->setTrustedOverlay(true);
3612 spyWindow->setSpy(true);
3613 sp<FakeWindowHandle> window =
3614 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3615 window->setNoInputChannel(true);
3616 window->setFrame(Rect(0, 0, 200, 200));
3617
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003618 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003619
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003620 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003621 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3622 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3623 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003624 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3625 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003626 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3627 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3628 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003629 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3630
3631 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003632 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3633 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3634 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003635 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3636
3637 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003638 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3639 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3640 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003641 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3642
3643 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003644 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3645 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3646 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003647 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3648 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003649 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3650 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3651 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003652 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3653
3654 // No more events
3655 spyWindow->assertNoEvents();
3656 window->assertNoEvents();
3657}
3658
3659/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003660 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3661 * rejected. But since we already have an ongoing gesture, this event should be processed.
3662 * This prevents inconsistent events being handled inside the dispatcher.
3663 */
3664TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3665 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3666
3667 sp<FakeWindowHandle> window =
3668 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3669 window->setFrame(Rect(0, 0, 200, 200));
3670
3671 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3672
3673 // Start hovering with stylus
3674 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3675 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3676 .build());
3677 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3678
3679 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3680 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3681 .build();
3682 // Make this 'hoverExit' event stale
3683 mFakePolicy->setStaleEventTimeout(100ms);
3684 std::this_thread::sleep_for(100ms);
3685
3686 // It shouldn't be dropped by the dispatcher, even though it's stale.
3687 mDispatcher->notifyMotion(hoverExit);
3688 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3689
3690 // Stylus starts hovering again! There should be no crash.
3691 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3692 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3693 .build());
3694 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3695}
3696
3697/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003698 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3699 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3700 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3701 * While the mouse is down, new move events from the touch device should be ignored.
3702 */
3703TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3704 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3705 sp<FakeWindowHandle> spyWindow =
3706 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3707 spyWindow->setFrame(Rect(0, 0, 200, 200));
3708 spyWindow->setTrustedOverlay(true);
3709 spyWindow->setSpy(true);
3710 sp<FakeWindowHandle> window =
3711 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3712 window->setFrame(Rect(0, 0, 200, 200));
3713
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003714 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003715
3716 const int32_t mouseDeviceId = 7;
3717 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003718
3719 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003720 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3721 .deviceId(mouseDeviceId)
3722 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3723 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003724 spyWindow->consumeMotionEvent(
3725 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3726 window->consumeMotionEvent(
3727 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3728
3729 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003730 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3731 .deviceId(touchDeviceId)
3732 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3733 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003734 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3735 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3736 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3737 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3738
Prabir Pradhan678438e2023-04-13 19:32:51 +00003739 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3740 .deviceId(touchDeviceId)
3741 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3742 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003743 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3744 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3745
3746 // Pilfer the stream
3747 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3748 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3749
Prabir Pradhan678438e2023-04-13 19:32:51 +00003750 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3751 .deviceId(touchDeviceId)
3752 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3753 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003754 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3755
3756 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003757 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3758 .deviceId(mouseDeviceId)
3759 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3760 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3761 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003762
3763 spyWindow->consumeMotionEvent(
3764 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3765 spyWindow->consumeMotionEvent(
3766 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3767 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3768
Prabir Pradhan678438e2023-04-13 19:32:51 +00003769 mDispatcher->notifyMotion(
3770 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3771 .deviceId(mouseDeviceId)
3772 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3773 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3774 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3775 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003776 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3777 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3778
3779 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003780 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3781 .deviceId(mouseDeviceId)
3782 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3783 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3784 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003785 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3786 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3787
3788 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003789 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3790 .deviceId(touchDeviceId)
3791 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3792 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003793
3794 // No more events
3795 spyWindow->assertNoEvents();
3796 window->assertNoEvents();
3797}
3798
3799/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003800 * On the display, have a single window, and also an area where there's no window.
3801 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3802 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3803 */
3804TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3805 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3806 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003807 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003808
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003809 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003810
3811 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003812 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003813
3814 mDispatcher->waitForIdle();
3815 window->assertNoEvents();
3816
3817 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003818 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003819 mDispatcher->waitForIdle();
3820 window->consumeMotionDown();
3821}
3822
3823/**
3824 * Same test as above, but instead of touching the empty space, the first touch goes to
3825 * non-touchable window.
3826 */
3827TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3828 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3829 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003830 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003831 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3832 window1->setTouchable(false);
3833 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003834 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003835 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3836
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003837 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003838
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003839 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003840 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003841
3842 mDispatcher->waitForIdle();
3843 window1->assertNoEvents();
3844 window2->assertNoEvents();
3845
3846 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003847 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003848 mDispatcher->waitForIdle();
3849 window2->consumeMotionDown();
3850}
3851
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003852/**
3853 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3854 * to the event time of the first ACTION_DOWN sent to the particular window.
3855 */
3856TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3857 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3858 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003859 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003860 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3861 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003862 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003863 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3864
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003865 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003866
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003867 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003868 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003869
3870 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003871
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08003872 std::unique_ptr<MotionEvent> motionEvent1 = window1->consumeMotionEvent();
3873 ASSERT_NE(nullptr, motionEvent1);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003874 window2->assertNoEvents();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08003875 nsecs_t downTimeForWindow1 = motionEvent1->getDownTime();
3876 ASSERT_EQ(motionEvent1->getDownTime(), motionEvent1->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003877
3878 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003879 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003880 mDispatcher->waitForIdle();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08003881 std::unique_ptr<MotionEvent> motionEvent2 = window2->consumeMotionEvent();
3882 ASSERT_NE(nullptr, motionEvent2);
3883 nsecs_t downTimeForWindow2 = motionEvent2->getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003884 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08003885 ASSERT_EQ(motionEvent2->getDownTime(), motionEvent2->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003886
3887 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003888 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003889 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003890 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003891
3892 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003893 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003894 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003895 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003896
3897 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3898 window1->consumeMotionMove();
3899 window1->assertNoEvents();
3900
3901 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003902 mDispatcher->notifyMotion(
3903 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003904 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003905 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003906
Prabir Pradhan678438e2023-04-13 19:32:51 +00003907 mDispatcher->notifyMotion(
3908 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003909 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003910 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003911}
3912
Garfield Tandf26e862020-07-01 20:18:19 -07003913TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003914 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003915 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003916 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003917 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003918 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003919 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003920 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003921
3922 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3923
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003924 mDispatcher->onWindowInfosChanged(
3925 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003926
3927 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003928 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003929 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003930 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3931 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003932 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003933 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003934 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003935
3936 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003937 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003938 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003939 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3940 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003941 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003942 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003943 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3944 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003945
3946 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003947 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003948 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003949 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3950 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003951 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003952 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003953 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3954 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003955
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003956 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003957 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003958 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3959 AINPUT_SOURCE_MOUSE)
3960 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3961 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003962 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003963 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003964 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003965
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003966 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003967 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003968 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3969 AINPUT_SOURCE_MOUSE)
3970 .buttonState(0)
3971 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003972 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003973 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003974 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003975
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003976 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003977 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003978 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3979 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003980 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003981 .build()));
3982 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3983
3984 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003985 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003986 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003987 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3988 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003989 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003990 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003991 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003992
3993 // No more events
3994 windowLeft->assertNoEvents();
3995 windowRight->assertNoEvents();
3996}
3997
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003998/**
3999 * Put two fingers down (and don't release them) and click the mouse button.
4000 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
4001 * currently active gesture should be canceled, and the new one should proceed.
4002 */
4003TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
4004 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4005 sp<FakeWindowHandle> window =
4006 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4007 window->setFrame(Rect(0, 0, 600, 800));
4008
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004009 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004010
4011 const int32_t touchDeviceId = 4;
4012 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004013
4014 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004015 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4016 .deviceId(touchDeviceId)
4017 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4018 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004019
Prabir Pradhan678438e2023-04-13 19:32:51 +00004020 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4021 .deviceId(touchDeviceId)
4022 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4023 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4024 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004025 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4026 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4027
4028 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00004029 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4030 .deviceId(mouseDeviceId)
4031 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4032 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4033 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004034 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
4035 WithPointerCount(2u)));
4036 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4037
Prabir Pradhan678438e2023-04-13 19:32:51 +00004038 mDispatcher->notifyMotion(
4039 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4040 .deviceId(mouseDeviceId)
4041 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4042 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4043 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4044 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004045 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4046
4047 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4048 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004049 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4050 .deviceId(touchDeviceId)
4051 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4052 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4053 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004054 window->assertNoEvents();
4055}
4056
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004057TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
4058 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4059
4060 sp<FakeWindowHandle> spyWindow =
4061 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4062 spyWindow->setFrame(Rect(0, 0, 600, 800));
4063 spyWindow->setTrustedOverlay(true);
4064 spyWindow->setSpy(true);
4065 sp<FakeWindowHandle> window =
4066 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4067 window->setFrame(Rect(0, 0, 600, 800));
4068
4069 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004070 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004071
4072 // Send mouse cursor to the window
4073 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004074 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004075 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4076 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004077 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004078 .build()));
4079
4080 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4081 WithSource(AINPUT_SOURCE_MOUSE)));
4082 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4083 WithSource(AINPUT_SOURCE_MOUSE)));
4084
4085 window->assertNoEvents();
4086 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004087}
4088
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004089TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
4090 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4091
4092 sp<FakeWindowHandle> spyWindow =
4093 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4094 spyWindow->setFrame(Rect(0, 0, 600, 800));
4095 spyWindow->setTrustedOverlay(true);
4096 spyWindow->setSpy(true);
4097 sp<FakeWindowHandle> window =
4098 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4099 window->setFrame(Rect(0, 0, 600, 800));
4100
4101 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004102 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004103
4104 // Send mouse cursor to the window
4105 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004106 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004107 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4108 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004109 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004110 .build()));
4111
4112 // Move mouse cursor
4113 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004114 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004115 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4116 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004117 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004118 .build()));
4119
4120 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4121 WithSource(AINPUT_SOURCE_MOUSE)));
4122 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4123 WithSource(AINPUT_SOURCE_MOUSE)));
4124 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4125 WithSource(AINPUT_SOURCE_MOUSE)));
4126 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4127 WithSource(AINPUT_SOURCE_MOUSE)));
4128 // Touch down on the window
4129 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004130 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004131 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4132 AINPUT_SOURCE_TOUCHSCREEN)
4133 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004134 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004135 .build()));
4136 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4137 WithSource(AINPUT_SOURCE_MOUSE)));
4138 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4139 WithSource(AINPUT_SOURCE_MOUSE)));
4140 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4141 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4142 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4143 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4144
4145 // pilfer the motion, retaining the gesture on the spy window.
4146 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4147 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4148 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4149
4150 // Touch UP on the window
4151 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004152 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004153 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4154 AINPUT_SOURCE_TOUCHSCREEN)
4155 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004156 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004157 .build()));
4158 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4159 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4160
4161 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4162 // to send a new gesture. It should again go to both windows (spy and the window below), just
4163 // like the first gesture did, before pilfering. The window configuration has not changed.
4164
4165 // One more tap - DOWN
4166 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004167 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004168 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4169 AINPUT_SOURCE_TOUCHSCREEN)
4170 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004171 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004172 .build()));
4173 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4174 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4175 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4176 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4177
4178 // Touch UP on the window
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_UP,
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_UP),
4187 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4188 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4189 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4190
4191 window->assertNoEvents();
4192 spyWindow->assertNoEvents();
4193}
4194
Garfield Tandf26e862020-07-01 20:18:19 -07004195// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
4196// directly in this test.
4197TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004198 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07004199 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004200 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004201 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004202
4203 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4204
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004205 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004206
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004207 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004208 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004209 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4210 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004211 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004212 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004213 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004214 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004215 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004216 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004217 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4218 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004219 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004220 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004221 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4222 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004223
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004224 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004225 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004226 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4227 AINPUT_SOURCE_MOUSE)
4228 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4229 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004230 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004231 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004232 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004233
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004234 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004235 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004236 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4237 AINPUT_SOURCE_MOUSE)
4238 .buttonState(0)
4239 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004240 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004241 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004242 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004243
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004244 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004245 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004246 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4247 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004248 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004249 .build()));
4250 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
4251
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07004252 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
4253 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
4254 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004255 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004256 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
4257 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004258 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004259 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004260 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004261}
4262
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004263/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004264 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
4265 * is generated.
4266 */
4267TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
4268 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4269 sp<FakeWindowHandle> window =
4270 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4271 window->setFrame(Rect(0, 0, 1200, 800));
4272
4273 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4274
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004275 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004276
4277 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004278 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004279 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4280 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004281 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004282 .build()));
4283 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4284
4285 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004286 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004287 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4288}
4289
4290/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004291 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4292 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004293TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4294 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4295 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004296 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4297 sp<FakeWindowHandle> window =
4298 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4299 window->setFrame(Rect(0, 0, 1200, 800));
4300
4301 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4302
4303 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4304
4305 MotionEventBuilder hoverEnterBuilder =
4306 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4307 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4308 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4309 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4310 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4311 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4312 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4313 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4314 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4315}
4316
4317/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004318 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4319 */
4320TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4321 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4322 sp<FakeWindowHandle> window =
4323 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4324 window->setFrame(Rect(0, 0, 100, 100));
4325
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004326 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004327
4328 const int32_t mouseDeviceId = 7;
4329 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004330
4331 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004332 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4333 .deviceId(mouseDeviceId)
4334 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4335 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004336 window->consumeMotionEvent(
4337 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4338
4339 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004340 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4341 .deviceId(touchDeviceId)
4342 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4343 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004344
4345 window->consumeMotionEvent(
4346 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4347 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4348}
4349
4350/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004351 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004352 * The tap causes a HOVER_EXIT event to be generated because the current event
4353 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004354 */
4355TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4356 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4357 sp<FakeWindowHandle> window =
4358 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4359 window->setFrame(Rect(0, 0, 100, 100));
4360
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004361 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004362 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4363 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4364 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004365 ASSERT_NO_FATAL_FAILURE(
4366 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4367 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004368
4369 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004370 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4371 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4372 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004373 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004374 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4375 WithSource(AINPUT_SOURCE_MOUSE))));
4376
4377 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004378 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4379 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4380
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004381 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4382 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4383 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004384 ASSERT_NO_FATAL_FAILURE(
4385 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4386 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4387}
4388
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004389TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4390 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4391 sp<FakeWindowHandle> windowDefaultDisplay =
4392 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4393 ADISPLAY_ID_DEFAULT);
4394 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4395 sp<FakeWindowHandle> windowSecondDisplay =
4396 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4397 SECOND_DISPLAY_ID);
4398 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4399
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004400 mDispatcher->onWindowInfosChanged(
4401 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004402
4403 // Set cursor position in window in default display and check that hover enter and move
4404 // events are generated.
4405 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004406 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004407 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4408 AINPUT_SOURCE_MOUSE)
4409 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004410 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004411 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004412 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004413
4414 // Remove all windows in secondary display and check that no event happens on window in
4415 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004416 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4417
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004418 windowDefaultDisplay->assertNoEvents();
4419
4420 // Move cursor position in window in default display and check that only hover move
4421 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004422 mDispatcher->onWindowInfosChanged(
4423 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004424 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004425 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004426 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4427 AINPUT_SOURCE_MOUSE)
4428 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004429 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004430 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004431 windowDefaultDisplay->consumeMotionEvent(
4432 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4433 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004434 windowDefaultDisplay->assertNoEvents();
4435}
4436
Garfield Tan00f511d2019-06-12 16:55:40 -07004437TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004438 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004439
4440 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004441 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004442 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004443 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004444 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004445 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004446
4447 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4448
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004449 mDispatcher->onWindowInfosChanged(
4450 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004451
4452 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4453 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004454 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004455 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004456 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004457 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004458 windowRight->assertNoEvents();
4459}
4460
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004461TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004462 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004463 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4464 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004465 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004466
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004467 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004468 setFocusedWindow(window);
4469
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004470 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004471
Prabir Pradhan678438e2023-04-13 19:32:51 +00004472 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004473
4474 // Window should receive key down event.
4475 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4476
4477 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4478 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004479 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004480 window->consumeKeyUp(ADISPLAY_ID_DEFAULT, AKEY_EVENT_FLAG_CANCELED);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004481}
4482
4483TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004484 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004485 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4486 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004487
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004488 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004489
Prabir Pradhan678438e2023-04-13 19:32:51 +00004490 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4491 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004492
4493 // Window should receive motion down event.
4494 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4495
4496 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4497 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004498 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004499 window->consumeMotionEvent(
4500 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004501}
4502
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004503TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4504 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4505 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4506 "Fake Window", ADISPLAY_ID_DEFAULT);
4507
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004508 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004509
4510 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4511 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4512 .build());
4513
4514 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4515
4516 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4517 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4518 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4519
4520 // After the device has been reset, a new hovering stream can be sent to the window
4521 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4522 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4523 .build());
4524 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4525}
4526
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004527TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4528 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004529 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4530 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004531 window->setFocusable(true);
4532
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004533 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004534 setFocusedWindow(window);
4535
4536 window->consumeFocusEvent(true);
4537
Prabir Pradhan678438e2023-04-13 19:32:51 +00004538 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004539 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4540 const nsecs_t injectTime = keyArgs.eventTime;
4541 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004542 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004543 // The dispatching time should be always greater than or equal to intercept key timeout.
4544 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4545 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4546 std::chrono::nanoseconds(interceptKeyTimeout).count());
4547}
4548
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004549/**
4550 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4551 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004552TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4553 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004554 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4555 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004556 window->setFocusable(true);
4557
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004558 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004559 setFocusedWindow(window);
4560
4561 window->consumeFocusEvent(true);
4562
Prabir Pradhan678438e2023-04-13 19:32:51 +00004563 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004564 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004565
4566 // Set a value that's significantly larger than the default consumption timeout. If the
4567 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4568 mFakePolicy->setInterceptKeyTimeout(600ms);
4569 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4570 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004571 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4572}
4573
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004574/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004575 * Two windows. First is a regular window. Second does not overlap with the first, and has
4576 * WATCH_OUTSIDE_TOUCH.
4577 * Both windows are owned by the same UID.
4578 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4579 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4580 */
4581TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4582 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004583 sp<FakeWindowHandle> window =
4584 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004585 window->setFrame(Rect{0, 0, 100, 100});
4586
4587 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004588 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004589 ADISPLAY_ID_DEFAULT);
4590 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4591 outsideWindow->setWatchOutsideTouch(true);
4592 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004593 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004594
4595 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004596 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4597 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4598 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004599 window->consumeMotionDown();
4600 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4601 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4602 outsideWindow->consumeMotionEvent(
4603 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00004604
4605 // Ensure outsideWindow doesn't get any more events for the gesture.
4606 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4607 ADISPLAY_ID_DEFAULT, {PointF{51, 51}}));
4608 window->consumeMotionMove();
4609 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004610}
4611
4612/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004613 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4614 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4615 * ACTION_OUTSIDE event is sent per gesture.
4616 */
4617TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4618 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4619 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004620 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4621 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004622 window->setWatchOutsideTouch(true);
4623 window->setFrame(Rect{0, 0, 100, 100});
4624 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004625 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4626 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004627 secondWindow->setFrame(Rect{100, 100, 200, 200});
4628 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004629 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4630 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004631 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004632 mDispatcher->onWindowInfosChanged(
4633 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004634
4635 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004636 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4637 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4638 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004639 window->assertNoEvents();
4640 secondWindow->assertNoEvents();
4641
4642 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4643 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004644 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4645 ADISPLAY_ID_DEFAULT,
4646 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004647 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4648 window->consumeMotionEvent(
4649 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004650 secondWindow->consumeMotionDown();
4651 thirdWindow->assertNoEvents();
4652
4653 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4654 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004655 mDispatcher->notifyMotion(
4656 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4657 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004658 window->assertNoEvents();
4659 secondWindow->consumeMotionMove();
4660 thirdWindow->consumeMotionDown();
4661}
4662
Prabir Pradhan814fe082022-07-22 20:22:18 +00004663TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4664 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004665 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4666 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004667 window->setFocusable(true);
4668
Patrick Williamsd828f302023-04-28 17:52:08 -05004669 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004670 setFocusedWindow(window);
4671
4672 window->consumeFocusEvent(true);
4673
Prabir Pradhan678438e2023-04-13 19:32:51 +00004674 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4675 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4676 mDispatcher->notifyKey(keyDown);
4677 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004678
4679 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4680 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4681
4682 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004683 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004684
4685 window->consumeFocusEvent(false);
4686
Prabir Pradhan678438e2023-04-13 19:32:51 +00004687 mDispatcher->notifyKey(keyDown);
4688 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004689 window->assertNoEvents();
4690}
4691
Arthur Hung96483742022-11-15 03:30:48 +00004692TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4693 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4694 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4695 "Fake Window", ADISPLAY_ID_DEFAULT);
4696 // Ensure window is non-split and have some transform.
4697 window->setPreventSplitting(true);
4698 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004699 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004700
4701 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004702 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004703 {50, 50}))
4704 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4705 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4706
4707 const MotionEvent secondFingerDownEvent =
4708 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4709 .displayId(ADISPLAY_ID_DEFAULT)
4710 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004711 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4712 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004713 .build();
4714 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004715 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004716 InputEventInjectionSync::WAIT_FOR_RESULT))
4717 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4718
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004719 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
4720 ASSERT_NE(nullptr, event);
4721 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4722 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4723 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4724 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4725 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
Arthur Hung96483742022-11-15 03:30:48 +00004726}
4727
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004728/**
4729 * Two windows: a splittable and a non-splittable.
4730 * The non-splittable window shouldn't receive any "incomplete" gestures.
4731 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4732 * The second pointer should be dropped because the initial window is splittable, so it won't get
4733 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4734 * "incomplete" gestures.
4735 */
4736TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4737 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4738 sp<FakeWindowHandle> leftWindow =
4739 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4740 ADISPLAY_ID_DEFAULT);
4741 leftWindow->setPreventSplitting(false);
4742 leftWindow->setFrame(Rect(0, 0, 100, 100));
4743 sp<FakeWindowHandle> rightWindow =
4744 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4745 ADISPLAY_ID_DEFAULT);
4746 rightWindow->setPreventSplitting(true);
4747 rightWindow->setFrame(Rect(100, 100, 200, 200));
4748 mDispatcher->onWindowInfosChanged(
4749 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4750
4751 // Touch down on left, splittable window
4752 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4753 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4754 .build());
4755 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4756
4757 mDispatcher->notifyMotion(
4758 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4759 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4760 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4761 .build());
4762 leftWindow->assertNoEvents();
4763 rightWindow->assertNoEvents();
4764}
4765
Harry Cuttsb166c002023-05-09 13:06:05 +00004766TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4767 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4768 sp<FakeWindowHandle> window =
4769 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4770 window->setFrame(Rect(0, 0, 400, 400));
4771 sp<FakeWindowHandle> trustedOverlay =
4772 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4773 ADISPLAY_ID_DEFAULT);
4774 trustedOverlay->setSpy(true);
4775 trustedOverlay->setTrustedOverlay(true);
4776
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004777 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004778
4779 // Start a three-finger touchpad swipe
4780 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4781 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4782 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4783 .build());
4784 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4785 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4786 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4787 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4788 .build());
4789 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4790 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4791 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4792 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4793 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4794 .build());
4795
4796 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4797 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4798 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4799
4800 // Move the swipe a bit
4801 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4802 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4803 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4804 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4805 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4806 .build());
4807
4808 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4809
4810 // End the swipe
4811 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4812 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4813 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4814 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4815 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4816 .build());
4817 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4818 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4819 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4820 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4821 .build());
4822 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4823 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4824 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4825 .build());
4826
4827 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4828 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4829 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4830
4831 window->assertNoEvents();
4832}
4833
4834TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4835 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4836 sp<FakeWindowHandle> window =
4837 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4838 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004839 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004840
4841 // Start a three-finger touchpad swipe
4842 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4843 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4844 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4845 .build());
4846 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4847 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4848 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4849 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4850 .build());
4851 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4852 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4853 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4854 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4855 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4856 .build());
4857
4858 // Move the swipe a bit
4859 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4860 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4861 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4862 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4863 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4864 .build());
4865
4866 // End the swipe
4867 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4868 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4869 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4870 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4871 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4872 .build());
4873 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4874 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4875 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4876 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4877 .build());
4878 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4879 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4880 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4881 .build());
4882
4883 window->assertNoEvents();
4884}
4885
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004886/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004887 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4888 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004889 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004890 */
4891TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4892 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4893 sp<FakeWindowHandle> window =
4894 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4895 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004896 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004897
4898 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4899 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4900 .downTime(baseTime + 10)
4901 .eventTime(baseTime + 10)
4902 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4903 .build());
4904
4905 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4906
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004907 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004908 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004909
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004910 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004911
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004912 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4913 .downTime(baseTime + 10)
4914 .eventTime(baseTime + 30)
4915 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4916 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4917 .build());
4918
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004919 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4920
4921 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004922 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4923 .downTime(baseTime + 10)
4924 .eventTime(baseTime + 40)
4925 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4926 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4927 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004928
4929 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4930
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004931 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4932 .downTime(baseTime + 10)
4933 .eventTime(baseTime + 50)
4934 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4935 .build());
4936
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004937 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4938
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004939 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4940 .downTime(baseTime + 60)
4941 .eventTime(baseTime + 60)
4942 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4943 .build());
4944
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004945 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004946}
4947
4948/**
Hu Guo771a7692023-09-17 20:51:08 +08004949 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4950 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4951 * its coordinates should be converted by the transform of the windows of target screen.
4952 */
4953TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4954 // This case will create a window and a spy window on the default display and mirror
4955 // window on the second display. cancel event is sent through spy window pilferPointers
4956 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4957
4958 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4959 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4960 spyWindowDefaultDisplay->setTrustedOverlay(true);
4961 spyWindowDefaultDisplay->setSpy(true);
4962
4963 sp<FakeWindowHandle> windowDefaultDisplay =
4964 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4965 ADISPLAY_ID_DEFAULT);
4966 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4967
4968 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4969 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4970
4971 // Add the windows to the dispatcher
4972 mDispatcher->onWindowInfosChanged(
4973 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4974 *windowSecondDisplay->getInfo()},
4975 {},
4976 0,
4977 0});
4978
4979 // Send down to ADISPLAY_ID_DEFAULT
4980 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4981 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4982 {100, 100}))
4983 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4984
4985 spyWindowDefaultDisplay->consumeMotionDown();
4986 windowDefaultDisplay->consumeMotionDown();
4987
4988 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4989
4990 // windowDefaultDisplay gets cancel
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004991 std::unique_ptr<MotionEvent> event = windowDefaultDisplay->consumeMotionEvent();
4992 ASSERT_NE(nullptr, event);
4993 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
Hu Guo771a7692023-09-17 20:51:08 +08004994
4995 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4996 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4997 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4998 // SECOND_DISPLAY_ID, the x and y coordinates are 200
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004999 EXPECT_EQ(100, event->getX(0));
5000 EXPECT_EQ(100, event->getY(0));
Hu Guo771a7692023-09-17 20:51:08 +08005001}
5002
5003/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005004 * Ensure the correct coordinate spaces are used by InputDispatcher.
5005 *
5006 * InputDispatcher works in the display space, so its coordinate system is relative to the display
5007 * panel. Windows get events in the window space, and get raw coordinates in the logical display
5008 * space.
5009 */
5010class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
5011public:
5012 void SetUp() override {
5013 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005014 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005015 }
5016
5017 void addDisplayInfo(int displayId, const ui::Transform& transform) {
5018 gui::DisplayInfo info;
5019 info.displayId = displayId;
5020 info.transform = transform;
5021 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05005022 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005023 }
5024
5025 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
5026 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05005027 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005028 }
5029
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005030 void removeAllWindowsAndDisplays() {
5031 mDisplayInfos.clear();
5032 mWindowInfos.clear();
5033 }
5034
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005035 // Set up a test scenario where the display has a scaled projection and there are two windows
5036 // on the display.
5037 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
5038 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
5039 // respectively.
5040 ui::Transform displayTransform;
5041 displayTransform.set(2, 0, 0, 4);
5042 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5043
5044 std::shared_ptr<FakeApplicationHandle> application =
5045 std::make_shared<FakeApplicationHandle>();
5046
5047 // Add two windows to the display. Their frames are represented in the display space.
5048 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005049 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5050 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005051 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
5052 addWindow(firstWindow);
5053
5054 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005055 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5056 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005057 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
5058 addWindow(secondWindow);
5059 return {std::move(firstWindow), std::move(secondWindow)};
5060 }
5061
5062private:
5063 std::vector<gui::DisplayInfo> mDisplayInfos;
5064 std::vector<gui::WindowInfo> mWindowInfos;
5065};
5066
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005067TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005068 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5069 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005070 // selected so that if the hit test was performed with the point and the bounds being in
5071 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005072 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5073 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5074 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005075
5076 firstWindow->consumeMotionDown();
5077 secondWindow->assertNoEvents();
5078}
5079
5080// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
5081// the event should be treated as being in the logical display space.
5082TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
5083 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5084 // Send down to the first window. The point is represented in the logical display space. The
5085 // point is selected so that if the hit test was done in logical display space, then it would
5086 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005087 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005088 PointF{75 * 2, 55 * 4});
5089
5090 firstWindow->consumeMotionDown();
5091 secondWindow->assertNoEvents();
5092}
5093
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005094// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
5095// event should be treated as being in the logical display space.
5096TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
5097 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5098
5099 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5100 ui::Transform injectedEventTransform;
5101 injectedEventTransform.set(matrix);
5102 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
5103 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
5104
5105 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5106 .displayId(ADISPLAY_ID_DEFAULT)
5107 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005108 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005109 .x(untransformedPoint.x)
5110 .y(untransformedPoint.y))
5111 .build();
5112 event.transform(matrix);
5113
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005114 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005115 InputEventInjectionSync::WAIT_FOR_RESULT);
5116
5117 firstWindow->consumeMotionDown();
5118 secondWindow->assertNoEvents();
5119}
5120
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005121TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
5122 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5123
5124 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005125 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5126 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5127 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005128
5129 firstWindow->assertNoEvents();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005130 std::unique_ptr<MotionEvent> event = secondWindow->consumeMotionEvent();
5131 ASSERT_NE(nullptr, event);
5132 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005133
5134 // Ensure that the events from the "getRaw" API are in logical display coordinates.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005135 EXPECT_EQ(300, event->getRawX(0));
5136 EXPECT_EQ(880, event->getRawY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005137
5138 // Ensure that the x and y values are in the window's coordinate space.
5139 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
5140 // the logical display space. This will be the origin of the window space.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005141 EXPECT_EQ(100, event->getX(0));
5142 EXPECT_EQ(80, event->getY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005143}
5144
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005145TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
5146 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5147 // The monitor will always receive events in the logical display's coordinate space, because
5148 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00005149 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005150
5151 // Send down to the first window.
5152 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5153 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5154 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5155 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5156
5157 // Second pointer goes down on second window.
5158 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5159 ADISPLAY_ID_DEFAULT,
5160 {PointF{50, 100}, PointF{150, 220}}));
5161 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
5162 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
5163 {1, PointF{300, 880}}};
5164 monitor.consumeMotionEvent(
5165 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
5166
5167 mDispatcher->cancelCurrentTouch();
5168
5169 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5170 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
5171 monitor.consumeMotionEvent(
5172 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
5173}
5174
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005175TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
5176 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5177
5178 // Send down to the first window.
5179 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5180 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5181 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5182
5183 // The pointer is transferred to the second window, and the second window receives it in the
5184 // correct coordinate space.
5185 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5186 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5187 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
5188}
5189
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005190TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
5191 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5192
5193 // Send hover move to the second window, and ensure it shows up as hover enter.
5194 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5195 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5196 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5197 WithCoords(100, 80), WithRawCoords(300, 880)));
5198
5199 // Touch down at the same location and ensure a hover exit is synthesized.
5200 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5201 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5202 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5203 WithRawCoords(300, 880)));
5204 secondWindow->consumeMotionEvent(
5205 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5206 secondWindow->assertNoEvents();
5207 firstWindow->assertNoEvents();
5208}
5209
Prabir Pradhan453ae732023-10-13 14:30:14 +00005210// Same as above, but while the window is being mirrored.
5211TEST_F(InputDispatcherDisplayProjectionTest,
5212 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
5213 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5214
5215 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5216 ui::Transform secondDisplayTransform;
5217 secondDisplayTransform.set(matrix);
5218 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5219
5220 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5221 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5222 addWindow(secondWindowClone);
5223
5224 // Send hover move to the second window, and ensure it shows up as hover enter.
5225 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5226 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5227 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5228 WithCoords(100, 80), WithRawCoords(300, 880)));
5229
5230 // Touch down at the same location and ensure a hover exit is synthesized for the correct
5231 // display.
5232 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5233 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5234 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5235 WithRawCoords(300, 880)));
5236 secondWindow->consumeMotionEvent(
5237 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5238 secondWindow->assertNoEvents();
5239 firstWindow->assertNoEvents();
5240}
5241
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005242TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
5243 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5244
5245 // Send hover enter to second window
5246 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5247 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5248 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5249 WithCoords(100, 80), WithRawCoords(300, 880)));
5250
5251 mDispatcher->cancelCurrentTouch();
5252
5253 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5254 WithRawCoords(300, 880)));
5255 secondWindow->assertNoEvents();
5256 firstWindow->assertNoEvents();
5257}
5258
Prabir Pradhan453ae732023-10-13 14:30:14 +00005259// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00005260TEST_F(InputDispatcherDisplayProjectionTest,
5261 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
5262 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5263
5264 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5265 ui::Transform secondDisplayTransform;
5266 secondDisplayTransform.set(matrix);
5267 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5268
5269 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5270 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5271 addWindow(secondWindowClone);
5272
5273 // Send hover enter to second window
5274 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5275 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5276 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5277 WithCoords(100, 80), WithRawCoords(300, 880),
5278 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5279
5280 mDispatcher->cancelCurrentTouch();
5281
5282 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
5283 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5284 WithRawCoords(300, 880),
5285 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5286 secondWindow->assertNoEvents();
5287 firstWindow->assertNoEvents();
5288}
5289
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005290/** Ensure consistent behavior of InputDispatcher in all orientations. */
5291class InputDispatcherDisplayOrientationFixture
5292 : public InputDispatcherDisplayProjectionTest,
5293 public ::testing::WithParamInterface<ui::Rotation> {};
5294
5295// This test verifies the touchable region of a window for all rotations of the display by tapping
5296// in different locations on the display, specifically points close to the four corners of a
5297// window.
5298TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
5299 constexpr static int32_t displayWidth = 400;
5300 constexpr static int32_t displayHeight = 800;
5301
5302 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5303
5304 const auto rotation = GetParam();
5305
5306 // Set up the display with the specified rotation.
5307 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5308 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5309 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5310 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5311 logicalDisplayWidth, logicalDisplayHeight);
5312 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5313
5314 // Create a window with its bounds determined in the logical display.
5315 const Rect frameInLogicalDisplay(100, 100, 200, 300);
5316 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
5317 sp<FakeWindowHandle> window =
5318 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5319 window->setFrame(frameInDisplay, displayTransform);
5320 addWindow(window);
5321
5322 // The following points in logical display space should be inside the window.
5323 static const std::array<vec2, 4> insidePoints{
5324 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5325 for (const auto pointInsideWindow : insidePoints) {
5326 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
5327 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005328 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5329 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5330 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005331 window->consumeMotionDown();
5332
Prabir Pradhan678438e2023-04-13 19:32:51 +00005333 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5334 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5335 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005336 window->consumeMotionUp();
5337 }
5338
5339 // The following points in logical display space should be outside the window.
5340 static const std::array<vec2, 5> outsidePoints{
5341 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
5342 for (const auto pointOutsideWindow : outsidePoints) {
5343 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
5344 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005345 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5346 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5347 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005348
Prabir Pradhan678438e2023-04-13 19:32:51 +00005349 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5350 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5351 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005352 }
5353 window->assertNoEvents();
5354}
5355
5356// Run the precision tests for all rotations.
5357INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
5358 InputDispatcherDisplayOrientationFixture,
5359 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
5360 ui::ROTATION_270),
5361 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
5362 return ftl::enum_string(testParamInfo.param);
5363 });
5364
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005365using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
5366 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005367
5368class TransferTouchFixture : public InputDispatcherTest,
5369 public ::testing::WithParamInterface<TransferFunction> {};
5370
5371TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07005372 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005373
5374 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005375 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005376 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5377 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005378 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005379 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005380 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5381 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005382 sp<FakeWindowHandle> wallpaper =
5383 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
5384 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005385 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005386 mDispatcher->onWindowInfosChanged(
5387 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005388
5389 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005390 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5391 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005392
Svet Ganov5d3bc372020-01-26 23:11:07 -08005393 // Only the first window should get the down event
5394 firstWindow->consumeMotionDown();
5395 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005396 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005397
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005398 // Transfer touch to the second window
5399 TransferFunction f = GetParam();
5400 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5401 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005402 // The first window gets cancel and the second gets down
5403 firstWindow->consumeMotionCancel();
5404 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005405 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005406
5407 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005408 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5409 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005410 // The first window gets no events and the second gets up
5411 firstWindow->assertNoEvents();
5412 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005413 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005414}
5415
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005416/**
5417 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
5418 * from. When we have spy windows, there are several windows to choose from: either spy, or the
5419 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
5420 * natural to the user.
5421 * In this test, we are sending a pointer to both spy window and first window. We then try to
5422 * transfer touch to the second window. The dispatcher should identify the first window as the
5423 * one that should lose the gesture, and therefore the action should be to move the gesture from
5424 * the first window to the second.
5425 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
5426 * the other API, as well.
5427 */
5428TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5429 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5430
5431 // Create a couple of windows + a spy window
5432 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005433 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005434 spyWindow->setTrustedOverlay(true);
5435 spyWindow->setSpy(true);
5436 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005437 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005438 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005439 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005440
5441 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005442 mDispatcher->onWindowInfosChanged(
5443 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005444
5445 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005446 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5447 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005448 // Only the first window and spy should get the down event
5449 spyWindow->consumeMotionDown();
5450 firstWindow->consumeMotionDown();
5451
5452 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
5453 // if f === 'transferTouch'.
5454 TransferFunction f = GetParam();
5455 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5456 ASSERT_TRUE(success);
5457 // The first window gets cancel and the second gets down
5458 firstWindow->consumeMotionCancel();
5459 secondWindow->consumeMotionDown();
5460
5461 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005462 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5463 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005464 // The first window gets no events and the second+spy get up
5465 firstWindow->assertNoEvents();
5466 spyWindow->consumeMotionUp();
5467 secondWindow->consumeMotionUp();
5468}
5469
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005470TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005471 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005472
5473 PointF touchPoint = {10, 10};
5474
5475 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005476 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005477 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5478 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005479 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005480 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005481 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5482 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005483 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005484
5485 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005486 mDispatcher->onWindowInfosChanged(
5487 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005488
5489 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005490 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5491 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5492 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005493 // Only the first window should get the down event
5494 firstWindow->consumeMotionDown();
5495 secondWindow->assertNoEvents();
5496
5497 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005498 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5499 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005500 // Only the first window should get the pointer down event
5501 firstWindow->consumeMotionPointerDown(1);
5502 secondWindow->assertNoEvents();
5503
5504 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005505 TransferFunction f = GetParam();
5506 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5507 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005508 // The first window gets cancel and the second gets down and pointer down
5509 firstWindow->consumeMotionCancel();
5510 secondWindow->consumeMotionDown();
5511 secondWindow->consumeMotionPointerDown(1);
5512
5513 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005514 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5515 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005516 // The first window gets nothing and the second gets pointer up
5517 firstWindow->assertNoEvents();
5518 secondWindow->consumeMotionPointerUp(1);
5519
5520 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005521 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5522 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005523 // The first window gets nothing and the second gets up
5524 firstWindow->assertNoEvents();
5525 secondWindow->consumeMotionUp();
5526}
5527
Arthur Hungc539dbb2022-12-08 07:45:36 +00005528TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5529 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5530
5531 // Create a couple of windows
5532 sp<FakeWindowHandle> firstWindow =
5533 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5534 ADISPLAY_ID_DEFAULT);
5535 firstWindow->setDupTouchToWallpaper(true);
5536 sp<FakeWindowHandle> secondWindow =
5537 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5538 ADISPLAY_ID_DEFAULT);
5539 secondWindow->setDupTouchToWallpaper(true);
5540
5541 sp<FakeWindowHandle> wallpaper1 =
5542 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5543 wallpaper1->setIsWallpaper(true);
5544
5545 sp<FakeWindowHandle> wallpaper2 =
5546 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5547 wallpaper2->setIsWallpaper(true);
5548 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005549 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5550 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5551 {},
5552 0,
5553 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005554
5555 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005556 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5557 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005558
5559 // Only the first window should get the down event
5560 firstWindow->consumeMotionDown();
5561 secondWindow->assertNoEvents();
5562 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5563 wallpaper2->assertNoEvents();
5564
5565 // Transfer touch focus to the second window
5566 TransferFunction f = GetParam();
5567 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5568 ASSERT_TRUE(success);
5569
5570 // The first window gets cancel and the second gets down
5571 firstWindow->consumeMotionCancel();
5572 secondWindow->consumeMotionDown();
5573 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5574 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5575
5576 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005577 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5578 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005579 // The first window gets no events and the second gets up
5580 firstWindow->assertNoEvents();
5581 secondWindow->consumeMotionUp();
5582 wallpaper1->assertNoEvents();
5583 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5584}
5585
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005586// For the cases of single pointer touch and two pointers non-split touch, the api's
5587// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5588// for the case where there are multiple pointers split across several windows.
5589INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5590 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005591 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5592 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005593 return dispatcher->transferTouch(destChannelToken,
5594 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005595 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005596 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5597 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005598 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005599 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005600 }));
5601
Svet Ganov5d3bc372020-01-26 23:11:07 -08005602TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005603 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005604
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005605 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005606 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5607 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005608 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005609
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005610 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005611 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5612 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005613 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005614
5615 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005616 mDispatcher->onWindowInfosChanged(
5617 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005618
5619 PointF pointInFirst = {300, 200};
5620 PointF pointInSecond = {300, 600};
5621
5622 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005623 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5624 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5625 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005626 // Only the first window should get the down event
5627 firstWindow->consumeMotionDown();
5628 secondWindow->assertNoEvents();
5629
5630 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005631 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5632 ADISPLAY_ID_DEFAULT,
5633 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005634 // The first window gets a move and the second a down
5635 firstWindow->consumeMotionMove();
5636 secondWindow->consumeMotionDown();
5637
5638 // Transfer touch focus to the second window
5639 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5640 // The first window gets cancel and the new gets pointer down (it already saw down)
5641 firstWindow->consumeMotionCancel();
5642 secondWindow->consumeMotionPointerDown(1);
5643
5644 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005645 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5646 ADISPLAY_ID_DEFAULT,
5647 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005648 // The first window gets nothing and the second gets pointer up
5649 firstWindow->assertNoEvents();
5650 secondWindow->consumeMotionPointerUp(1);
5651
5652 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005653 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5654 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005655 // The first window gets nothing and the second gets up
5656 firstWindow->assertNoEvents();
5657 secondWindow->consumeMotionUp();
5658}
5659
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005660// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5661// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5662// touch is not supported, so the touch should continue on those windows and the transferred-to
5663// window should get nothing.
5664TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5665 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5666
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005667 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005668 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5669 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005670 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005671
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005672 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005673 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5674 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005675 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005676
5677 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005678 mDispatcher->onWindowInfosChanged(
5679 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005680
5681 PointF pointInFirst = {300, 200};
5682 PointF pointInSecond = {300, 600};
5683
5684 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005685 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5686 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5687 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005688 // Only the first window should get the down event
5689 firstWindow->consumeMotionDown();
5690 secondWindow->assertNoEvents();
5691
5692 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005693 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5694 ADISPLAY_ID_DEFAULT,
5695 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005696 // The first window gets a move and the second a down
5697 firstWindow->consumeMotionMove();
5698 secondWindow->consumeMotionDown();
5699
5700 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005701 const bool transferred =
5702 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005703 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5704 ASSERT_FALSE(transferred);
5705 firstWindow->assertNoEvents();
5706 secondWindow->assertNoEvents();
5707
5708 // The rest of the dispatch should proceed as normal
5709 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005710 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5711 ADISPLAY_ID_DEFAULT,
5712 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005713 // The first window gets MOVE and the second gets pointer up
5714 firstWindow->consumeMotionMove();
5715 secondWindow->consumeMotionUp();
5716
5717 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005718 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5719 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005720 // The first window gets nothing and the second gets up
5721 firstWindow->consumeMotionUp();
5722 secondWindow->assertNoEvents();
5723}
5724
Arthur Hungabbb9d82021-09-01 14:52:30 +00005725// This case will create two windows and one mirrored window on the default display and mirror
5726// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5727// the windows info of second display before default display.
5728TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5729 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5730 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005731 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005732 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005733 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005734 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005735 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005736
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005737 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005738 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005739
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005740 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005741 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005742
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005743 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005744 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005745
5746 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005747 mDispatcher->onWindowInfosChanged(
5748 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5749 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5750 *secondWindowInPrimary->getInfo()},
5751 {},
5752 0,
5753 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005754
5755 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005756 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005757 {50, 50}))
5758 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5759
5760 // Window should receive motion event.
5761 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5762
5763 // Transfer touch focus
5764 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5765 secondWindowInPrimary->getToken()));
5766 // The first window gets cancel.
5767 firstWindowInPrimary->consumeMotionCancel();
5768 secondWindowInPrimary->consumeMotionDown();
5769
5770 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005771 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005772 ADISPLAY_ID_DEFAULT, {150, 50}))
5773 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5774 firstWindowInPrimary->assertNoEvents();
5775 secondWindowInPrimary->consumeMotionMove();
5776
5777 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005778 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005779 {150, 50}))
5780 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5781 firstWindowInPrimary->assertNoEvents();
5782 secondWindowInPrimary->consumeMotionUp();
5783}
5784
5785// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5786// 'transferTouch' api.
5787TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5788 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5789 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005790 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005791 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005792 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005793 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005794 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005795
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005796 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005797 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005798
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005799 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005800 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005801
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005802 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005803 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005804
5805 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005806 mDispatcher->onWindowInfosChanged(
5807 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5808 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5809 *secondWindowInPrimary->getInfo()},
5810 {},
5811 0,
5812 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005813
5814 // Touch on second display.
5815 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005816 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5817 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005818 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5819
5820 // Window should receive motion event.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005821 firstWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005822
5823 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005824 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005825
5826 // The first window gets cancel.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005827 firstWindowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
5828 secondWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005829
5830 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005831 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005832 SECOND_DISPLAY_ID, {150, 50}))
5833 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005834 firstWindowInSecondary->assertNoEvents();
5835 secondWindowInSecondary->consumeMotionMove(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005836
5837 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005838 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005839 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005840 firstWindowInSecondary->assertNoEvents();
5841 secondWindowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005842}
5843
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005844TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005845 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005846 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5847 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005848
Vishnu Nair47074b82020-08-14 11:54:47 -07005849 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005850 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005851 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005852
5853 window->consumeFocusEvent(true);
5854
Prabir Pradhan678438e2023-04-13 19:32:51 +00005855 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005856
5857 // Window should receive key down event.
5858 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005859
5860 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005861 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005862 mFakePolicy->assertUserActivityPoked();
5863}
5864
5865TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5866 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5867 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5868 "Fake Window", ADISPLAY_ID_DEFAULT);
5869
5870 window->setDisableUserActivity(true);
5871 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005872 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005873 setFocusedWindow(window);
5874
5875 window->consumeFocusEvent(true);
5876
5877 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5878
5879 // Window should receive key down event.
5880 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5881
5882 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005883 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005884 mFakePolicy->assertUserActivityNotPoked();
5885}
5886
5887TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5888 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5889 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5890 "Fake Window", ADISPLAY_ID_DEFAULT);
5891
5892 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005893 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005894 setFocusedWindow(window);
5895
5896 window->consumeFocusEvent(true);
5897
5898 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5899 mDispatcher->waitForIdle();
5900
5901 // System key is not passed down
5902 window->assertNoEvents();
5903
5904 // Should have poked user activity
5905 mFakePolicy->assertUserActivityPoked();
5906}
5907
5908TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5909 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5910 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5911 "Fake Window", ADISPLAY_ID_DEFAULT);
5912
5913 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005914 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005915 setFocusedWindow(window);
5916
5917 window->consumeFocusEvent(true);
5918
5919 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5920 mDispatcher->waitForIdle();
5921
5922 // System key is not passed down
5923 window->assertNoEvents();
5924
5925 // Should have poked user activity
5926 mFakePolicy->assertUserActivityPoked();
5927}
5928
5929TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5930 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5931 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5932 "Fake Window", ADISPLAY_ID_DEFAULT);
5933
5934 window->setDisableUserActivity(true);
5935 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005936 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005937 setFocusedWindow(window);
5938
5939 window->consumeFocusEvent(true);
5940
5941 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5942 mDispatcher->waitForIdle();
5943
5944 // System key is not passed down
5945 window->assertNoEvents();
5946
5947 // Should have poked user activity
5948 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005949}
5950
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005951TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5952 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5953 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5954 "Fake Window", ADISPLAY_ID_DEFAULT);
5955
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005956 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005957
5958 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005959 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005960 ADISPLAY_ID_DEFAULT, {100, 100}))
5961 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5962
5963 window->consumeMotionEvent(
5964 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5965
5966 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005967 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005968 mFakePolicy->assertUserActivityPoked();
5969}
5970
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005971TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005972 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005973 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5974 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005975
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005976 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005977
Prabir Pradhan678438e2023-04-13 19:32:51 +00005978 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005979 mDispatcher->waitForIdle();
5980
5981 window->assertNoEvents();
5982}
5983
5984// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5985TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005986 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005987 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5988 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005989
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005990 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005991
5992 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005993 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005994 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005995 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5996 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005997
5998 // Window should receive only the motion event
5999 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6000 window->assertNoEvents(); // Key event or focus event will not be received
6001}
6002
arthurhungea3f4fc2020-12-21 23:18:53 +08006003TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
6004 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6005
arthurhungea3f4fc2020-12-21 23:18:53 +08006006 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006007 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
6008 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08006009 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08006010
arthurhungea3f4fc2020-12-21 23:18:53 +08006011 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006012 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
6013 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08006014 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08006015
6016 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006017 mDispatcher->onWindowInfosChanged(
6018 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08006019
6020 PointF pointInFirst = {300, 200};
6021 PointF pointInSecond = {300, 600};
6022
6023 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006024 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6025 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6026 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08006027 // Only the first window should get the down event
6028 firstWindow->consumeMotionDown();
6029 secondWindow->assertNoEvents();
6030
6031 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006032 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6033 ADISPLAY_ID_DEFAULT,
6034 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08006035 // The first window gets a move and the second a down
6036 firstWindow->consumeMotionMove();
6037 secondWindow->consumeMotionDown();
6038
6039 // Send pointer cancel to the second window
6040 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006041 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08006042 {pointInFirst, pointInSecond});
6043 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00006044 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08006045 // The first window gets move and the second gets cancel.
6046 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
6047 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
6048
6049 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00006050 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6051 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08006052 // The first window gets up and the second gets nothing.
6053 firstWindow->consumeMotionUp();
6054 secondWindow->assertNoEvents();
6055}
6056
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006057TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
6058 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6059
6060 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006061 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006062 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006063 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
6064 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
6065 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
6066
Harry Cutts33476232023-01-30 19:57:29 +00006067 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006068 window->assertNoEvents();
6069 mDispatcher->waitForIdle();
6070}
6071
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006072using InputDispatcherMonitorTest = InputDispatcherTest;
6073
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006074/**
6075 * Two entities that receive touch: A window, and a global monitor.
6076 * The touch goes to the window, and then the window disappears.
6077 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
6078 * for the monitor, as well.
6079 * 1. foregroundWindow
6080 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
6081 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006082TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006083 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6084 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006085 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006086
Prabir Pradhanfb549072023-10-05 19:17:36 +00006087 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006088
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006089 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006090 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006091 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006092 {100, 200}))
6093 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6094
6095 // Both the foreground window and the global monitor should receive the touch down
6096 window->consumeMotionDown();
6097 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6098
6099 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006100 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006101 ADISPLAY_ID_DEFAULT, {110, 200}))
6102 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6103
6104 window->consumeMotionMove();
6105 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6106
6107 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006108 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006109 window->consumeMotionCancel();
6110 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
6111
6112 // If more events come in, there will be no more foreground window to send them to. This will
6113 // cause a cancel for the monitor, as well.
6114 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006115 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006116 ADISPLAY_ID_DEFAULT, {120, 200}))
6117 << "Injection should fail because the window was removed";
6118 window->assertNoEvents();
6119 // Global monitor now gets the cancel
6120 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6121}
6122
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006123TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07006124 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006125 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6126 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006127 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006128
Prabir Pradhanfb549072023-10-05 19:17:36 +00006129 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006130
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006131 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006132 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006133 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00006134 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006135 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006136}
6137
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006138TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00006139 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006140
Chris Yea209fde2020-07-22 13:54:51 -07006141 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006142 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6143 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006144 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006145
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006146 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006147 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006148 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08006149 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006150 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006151
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006152 // Pilfer pointers from the monitor.
6153 // This should not do anything and the window should continue to receive events.
6154 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00006155
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006156 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006157 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006158 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006159 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006160
6161 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6162 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006163}
6164
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006165TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07006166 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006167 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6168 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006169 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07006170 window->setWindowOffset(20, 40);
6171 window->setWindowTransform(0, 1, -1, 0);
6172
Prabir Pradhanfb549072023-10-05 19:17:36 +00006173 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07006174
6175 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006176 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07006177 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6178 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006179 std::unique_ptr<MotionEvent> event = monitor.consumeMotion();
6180 ASSERT_NE(nullptr, event);
Evan Rosky84f07f02021-04-16 10:42:42 -07006181 // Even though window has transform, gesture monitor must not.
6182 ASSERT_EQ(ui::Transform(), event->getTransform());
6183}
6184
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006185TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00006186 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00006187 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00006188
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006189 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006190 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006191 << "Injection should fail if there is a monitor, but no touchable window";
6192 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00006193}
6194
Linnan Lid8150952024-01-26 18:07:17 +00006195/**
6196 * Two displays
6197 * The first monitor has a foreground window, a monitor
6198 * The second window has only one monitor.
6199 * We first inject a Down event into the first display, this injection should succeed and both
6200 * the foreground window and monitor should receive a down event, then inject a Down event into
6201 * the second display as well, this injection should fail, at this point, the first display
6202 * window and monitor should not receive a cancel or any other event.
6203 * Continue to inject Move and UP events to the first display, the events should be received
6204 * normally by the foreground window and monitor.
6205 */
6206TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCanceledWhenAnotherEmptyDisplayReceiveEvents) {
6207 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6208 sp<FakeWindowHandle> window =
6209 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6210
6211 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6212 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
6213
6214 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6215 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6216 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6217 {100, 200}))
6218 << "The down event injected into the first display should succeed";
6219
6220 window->consumeMotionDown();
6221 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006222
6223 ASSERT_EQ(InputEventInjectionResult::FAILED,
6224 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6225 {100, 200}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006226 << "The down event injected into the second display should fail since there's no "
6227 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006228
6229 // Continue to inject event to first display.
6230 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6231 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6232 ADISPLAY_ID_DEFAULT, {110, 220}))
6233 << "The move event injected into the first display should succeed";
6234
6235 window->consumeMotionMove();
6236 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006237
6238 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6239 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6240 {110, 220}))
6241 << "The up event injected into the first display should succeed";
6242
6243 window->consumeMotionUp();
6244 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006245
6246 window->assertNoEvents();
6247 monitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00006248 secondMonitor.assertNoEvents();
6249}
6250
6251/**
6252 * Two displays
6253 * There is a monitor and foreground window on each display.
6254 * First, we inject down events into each of the two displays, at this point, the foreground windows
6255 * and monitors on both displays should receive down events.
6256 * At this point, the foreground window of the second display goes away, the gone window should
6257 * receive the cancel event, and the other windows and monitors should not receive any events.
6258 * Inject a move event into the second display. At this point, the injection should fail because
6259 * the second display no longer has a foreground window. At this point, the monitor on the second
6260 * display should receive a cancel event, and any windows or monitors on the first display should
6261 * not receive any events, and any subsequent injection of events into the second display should
6262 * also fail.
6263 * Continue to inject events into the first display, and the events should all be injected
6264 * successfully and received normally.
6265 */
6266TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCancelWhenAnotherDisplayMonitorTouchCanceled) {
6267 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6268 sp<FakeWindowHandle> window =
6269 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6270 sp<FakeWindowHandle> secondWindow =
6271 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondForeground",
6272 SECOND_DISPLAY_ID);
6273
6274 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6275 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
6276
6277 // There is a foreground window on both displays.
6278 mDispatcher->onWindowInfosChanged({{*window->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
6279 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6280 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6281 {100, 200}))
6282 << "The down event injected into the first display should succeed";
6283
6284 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6285 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006286
6287 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6288 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6289 {100, 200}))
6290 << "The down event injected into the second display should succeed";
6291
Linnan Lid8150952024-01-26 18:07:17 +00006292 secondWindow->consumeMotionDown(SECOND_DISPLAY_ID);
6293 secondMonitor.consumeMotionDown(SECOND_DISPLAY_ID);
6294
6295 // Now second window is gone away.
6296 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6297
6298 // The gone window should receive a cancel, and the monitor on the second display should not
6299 // receive any events.
Linnan Lid8150952024-01-26 18:07:17 +00006300 secondWindow->consumeMotionCancel(SECOND_DISPLAY_ID);
6301 secondMonitor.assertNoEvents();
6302
6303 ASSERT_EQ(InputEventInjectionResult::FAILED,
6304 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6305 SECOND_DISPLAY_ID, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006306 << "The move event injected into the second display should fail because there's no "
6307 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006308 // Now the monitor on the second display should receive a cancel event.
6309 secondMonitor.consumeMotionCancel(SECOND_DISPLAY_ID);
Linnan Lid8150952024-01-26 18:07:17 +00006310
6311 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6312 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6313 ADISPLAY_ID_DEFAULT, {110, 200}))
6314 << "The move event injected into the first display should succeed";
6315
6316 window->consumeMotionMove();
6317 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006318
6319 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006320 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6321 {110, 220}))
6322 << "The up event injected into the second display should fail because there's no "
6323 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006324
6325 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6326 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6327 {110, 220}))
6328 << "The up event injected into the first display should succeed";
6329
6330 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6331 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006332
Linnan Lid8150952024-01-26 18:07:17 +00006333 window->assertNoEvents();
6334 monitor.assertNoEvents();
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006335 secondWindow->assertNoEvents();
6336 secondMonitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00006337}
6338
6339/**
6340 * One display with transform
6341 * There is a foreground window and a monitor on the display
6342 * Inject down event and move event sequentially, the foreground window and monitor can receive down
6343 * event and move event, then let the foreground window go away, the foreground window receives
6344 * cancel event, inject move event again, the monitor receives cancel event, all the events received
6345 * by the monitor should be with the same transform as the display
6346 */
6347TEST_F(InputDispatcherMonitorTest, MonitorTouchCancelEventWithDisplayTransform) {
6348 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6349 sp<FakeWindowHandle> window =
6350 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6351 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6352
6353 ui::Transform transform;
6354 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6355
6356 gui::DisplayInfo displayInfo;
6357 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6358 displayInfo.transform = transform;
6359
6360 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
6361
6362 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6363 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6364 {100, 200}))
6365 << "The down event injected should succeed";
6366
6367 window->consumeMotionDown();
6368 std::unique_ptr<MotionEvent> downMotionEvent = monitor.consumeMotion();
6369 EXPECT_EQ(transform, downMotionEvent->getTransform());
6370 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, downMotionEvent->getAction());
6371
6372 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6373 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6374 ADISPLAY_ID_DEFAULT, {110, 220}))
6375 << "The move event injected should succeed";
6376
6377 window->consumeMotionMove();
6378 std::unique_ptr<MotionEvent> moveMotionEvent = monitor.consumeMotion();
6379 EXPECT_EQ(transform, moveMotionEvent->getTransform());
6380 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, moveMotionEvent->getAction());
6381
6382 // Let foreground window gone
6383 mDispatcher->onWindowInfosChanged({{}, {displayInfo}, 0, 0});
6384
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006385 // Foreground window should receive a cancel event, but not the monitor.
Linnan Lid8150952024-01-26 18:07:17 +00006386 window->consumeMotionCancel();
Linnan Lid8150952024-01-26 18:07:17 +00006387
6388 ASSERT_EQ(InputEventInjectionResult::FAILED,
6389 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6390 ADISPLAY_ID_DEFAULT, {110, 220}))
6391 << "The move event injected should failed";
6392 // Now foreground should not receive any events, but monitor should receive a cancel event
6393 // with transform that same as display's display.
Linnan Lid8150952024-01-26 18:07:17 +00006394 std::unique_ptr<MotionEvent> cancelMotionEvent = monitor.consumeMotion();
6395 EXPECT_EQ(transform, cancelMotionEvent->getTransform());
6396 EXPECT_EQ(ADISPLAY_ID_DEFAULT, cancelMotionEvent->getDisplayId());
6397 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, cancelMotionEvent->getAction());
6398
6399 // Other event inject to this display should fail.
6400 ASSERT_EQ(InputEventInjectionResult::FAILED,
6401 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6402 ADISPLAY_ID_DEFAULT, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006403 << "The up event injected should fail because the touched window was removed";
Linnan Lid8150952024-01-26 18:07:17 +00006404 window->assertNoEvents();
6405 monitor.assertNoEvents();
6406}
6407
chaviw81e2bb92019-12-18 15:03:51 -08006408TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006409 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006410 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6411 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08006412
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006413 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08006414
6415 NotifyMotionArgs motionArgs =
6416 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6417 ADISPLAY_ID_DEFAULT);
6418
Prabir Pradhan678438e2023-04-13 19:32:51 +00006419 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08006420 // Window should receive motion down event.
6421 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6422
6423 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08006424 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08006425 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6426 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
6427 motionArgs.pointerCoords[0].getX() - 10);
6428
Prabir Pradhan678438e2023-04-13 19:32:51 +00006429 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006430 window->consumeMotionMove(ADISPLAY_ID_DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08006431}
6432
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006433/**
6434 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
6435 * the device default right away. In the test scenario, we check both the default value,
6436 * and the action of enabling / disabling.
6437 */
6438TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07006439 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006440 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6441 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08006442 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006443
6444 // Set focused application.
6445 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006446 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006447
6448 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006449 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006450 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006451 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006452
6453 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006454 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006455 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006456 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006457
6458 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006459 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006460 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006461 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07006462 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006463 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006464 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006465 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006466
6467 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006468 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006469 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006470 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006471
6472 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006473 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006474 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006475 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07006476 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006477 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006478 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006479 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006480
6481 window->assertNoEvents();
6482}
6483
Gang Wange9087892020-01-07 12:17:14 -05006484TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006485 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006486 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6487 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05006488
6489 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006490 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05006491
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006492 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006493 setFocusedWindow(window);
6494
Harry Cutts33476232023-01-30 19:57:29 +00006495 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05006496
Prabir Pradhan678438e2023-04-13 19:32:51 +00006497 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
6498 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05006499
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006500 std::unique_ptr<KeyEvent> event = window->consumeKey();
6501 ASSERT_NE(event, nullptr);
6502 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Gang Wange9087892020-01-07 12:17:14 -05006503 ASSERT_NE(verified, nullptr);
6504 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
6505
6506 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
6507 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
6508 ASSERT_EQ(keyArgs.source, verified->source);
6509 ASSERT_EQ(keyArgs.displayId, verified->displayId);
6510
6511 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
6512
6513 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05006514 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006515 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05006516 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
6517 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
6518 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
6519 ASSERT_EQ(0, verifiedKey.repeatCount);
6520}
6521
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006522TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006523 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006524 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6525 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006526
6527 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6528
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006529 ui::Transform transform;
6530 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6531
6532 gui::DisplayInfo displayInfo;
6533 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6534 displayInfo.transform = transform;
6535
Patrick Williamsd828f302023-04-28 17:52:08 -05006536 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006537
Prabir Pradhan678438e2023-04-13 19:32:51 +00006538 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006539 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6540 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006541 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006542
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006543 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
6544 ASSERT_NE(nullptr, event);
6545 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006546 ASSERT_NE(verified, nullptr);
6547 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
6548
6549 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
6550 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
6551 EXPECT_EQ(motionArgs.source, verified->source);
6552 EXPECT_EQ(motionArgs.displayId, verified->displayId);
6553
6554 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
6555
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006556 const vec2 rawXY =
6557 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
6558 motionArgs.pointerCoords[0].getXYValue());
6559 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
6560 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006561 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006562 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006563 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006564 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
6565 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
6566}
6567
chaviw09c8d2d2020-08-24 15:48:26 -07006568/**
6569 * Ensure that separate calls to sign the same data are generating the same key.
6570 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
6571 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
6572 * tests.
6573 */
6574TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
6575 KeyEvent event = getTestKeyEvent();
6576 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6577
6578 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
6579 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
6580 ASSERT_EQ(hmac1, hmac2);
6581}
6582
6583/**
6584 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6585 */
6586TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6587 KeyEvent event = getTestKeyEvent();
6588 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6589 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6590
6591 verifiedEvent.deviceId += 1;
6592 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6593
6594 verifiedEvent.source += 1;
6595 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6596
6597 verifiedEvent.eventTimeNanos += 1;
6598 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6599
6600 verifiedEvent.displayId += 1;
6601 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6602
6603 verifiedEvent.action += 1;
6604 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6605
6606 verifiedEvent.downTimeNanos += 1;
6607 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6608
6609 verifiedEvent.flags += 1;
6610 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6611
6612 verifiedEvent.keyCode += 1;
6613 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6614
6615 verifiedEvent.scanCode += 1;
6616 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6617
6618 verifiedEvent.metaState += 1;
6619 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6620
6621 verifiedEvent.repeatCount += 1;
6622 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6623}
6624
Vishnu Nair958da932020-08-21 17:12:37 -07006625TEST_F(InputDispatcherTest, SetFocusedWindow) {
6626 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6627 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006628 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006629 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006630 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006631 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6632
6633 // Top window is also focusable but is not granted focus.
6634 windowTop->setFocusable(true);
6635 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006636 mDispatcher->onWindowInfosChanged(
6637 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006638 setFocusedWindow(windowSecond);
6639
6640 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006642 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006643
6644 // Focused window should receive event.
6645 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6646 windowTop->assertNoEvents();
6647}
6648
6649TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
6650 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6651 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006652 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006653 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6654
6655 window->setFocusable(true);
6656 // Release channel for window is no longer valid.
6657 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006658 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006659 setFocusedWindow(window);
6660
6661 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006662 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006663
6664 // window channel is invalid, so it should not receive any input event.
6665 window->assertNoEvents();
6666}
6667
6668TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
6669 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6670 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006671 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006672 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006673 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6674
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006675 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006676 setFocusedWindow(window);
6677
6678 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006679 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006680
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006681 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006682 window->assertNoEvents();
6683}
6684
6685TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6686 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6687 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006688 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006689 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006690 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006691 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6692
6693 windowTop->setFocusable(true);
6694 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006695 mDispatcher->onWindowInfosChanged(
6696 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006697 setFocusedWindow(windowTop);
6698 windowTop->consumeFocusEvent(true);
6699
Chavi Weingarten847e8512023-03-29 00:26:09 +00006700 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006701 mDispatcher->onWindowInfosChanged(
6702 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006703 windowSecond->consumeFocusEvent(true);
6704 windowTop->consumeFocusEvent(false);
6705
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006706 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006707 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006708
6709 // Focused window should receive event.
6710 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6711}
6712
Chavi Weingarten847e8512023-03-29 00:26:09 +00006713TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006714 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6715 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006716 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006717 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006718 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006719 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6720
6721 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006722 windowSecond->setFocusable(false);
6723 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006724 mDispatcher->onWindowInfosChanged(
6725 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006726 setFocusedWindow(windowTop);
6727 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006728
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006729 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006730 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006731
6732 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006733 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006734 windowSecond->assertNoEvents();
6735}
6736
6737TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6738 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6739 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006740 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006741 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006742 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6743 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006744 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6745
6746 window->setFocusable(true);
6747 previousFocusedWindow->setFocusable(true);
6748 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006749 mDispatcher->onWindowInfosChanged(
6750 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006751 setFocusedWindow(previousFocusedWindow);
6752 previousFocusedWindow->consumeFocusEvent(true);
6753
6754 // Requesting focus on invisible window takes focus from currently focused window.
6755 setFocusedWindow(window);
6756 previousFocusedWindow->consumeFocusEvent(false);
6757
6758 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006759 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006760 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6761 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006762
6763 // Window does not get focus event or key down.
6764 window->assertNoEvents();
6765
6766 // Window becomes visible.
6767 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006768 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006769
6770 // Window receives focus event.
6771 window->consumeFocusEvent(true);
6772 // Focused window receives key down.
6773 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6774}
6775
Vishnu Nair599f1412021-06-21 10:39:58 -07006776TEST_F(InputDispatcherTest, DisplayRemoved) {
6777 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6778 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006779 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006780 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6781
6782 // window is granted focus.
6783 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006784 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006785 setFocusedWindow(window);
6786 window->consumeFocusEvent(true);
6787
6788 // When a display is removed window loses focus.
6789 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6790 window->consumeFocusEvent(false);
6791}
6792
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006793/**
6794 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6795 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6796 * of the 'slipperyEnterWindow'.
6797 *
6798 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6799 * a way so that the touched location is no longer covered by the top window.
6800 *
6801 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6802 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6803 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6804 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6805 * with ACTION_DOWN).
6806 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6807 * window moved itself away from the touched location and had Flag::SLIPPERY.
6808 *
6809 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6810 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6811 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6812 *
6813 * In this test, we ensure that the event received by the bottom window has
6814 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6815 */
6816TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006817 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006818 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006819
6820 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6821 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6822
6823 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006824 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006825 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006826 // Make sure this one overlaps the bottom window
6827 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6828 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6829 // one. Windows with the same owner are not considered to be occluding each other.
6830 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6831
6832 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006833 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006834 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6835
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006836 mDispatcher->onWindowInfosChanged(
6837 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006838
6839 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006840 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6841 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6842 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006843 slipperyExitWindow->consumeMotionDown();
6844 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006845 mDispatcher->onWindowInfosChanged(
6846 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006847
Prabir Pradhan678438e2023-04-13 19:32:51 +00006848 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6849 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6850 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006851
6852 slipperyExitWindow->consumeMotionCancel();
6853
6854 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6855 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6856}
6857
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006858/**
6859 * Two windows, one on the left and another on the right. The left window is slippery. The right
6860 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6861 * touch moves from the left window into the right window, the gesture should continue to go to the
6862 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6863 * reproduces a crash.
6864 */
6865TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6866 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6867
6868 sp<FakeWindowHandle> leftSlipperyWindow =
6869 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6870 leftSlipperyWindow->setSlippery(true);
6871 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6872
6873 sp<FakeWindowHandle> rightDropTouchesWindow =
6874 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6875 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6876 rightDropTouchesWindow->setDropInput(true);
6877
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006878 mDispatcher->onWindowInfosChanged(
6879 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006880
6881 // Start touch in the left window
6882 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6883 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6884 .build());
6885 leftSlipperyWindow->consumeMotionDown();
6886
6887 // And move it into the right window
6888 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6889 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6890 .build());
6891
6892 // Since the right window isn't eligible to receive input, touch does not slip.
6893 // The left window continues to receive the gesture.
6894 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6895 rightDropTouchesWindow->assertNoEvents();
6896}
6897
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006898/**
6899 * A single window is on screen first. Touch is injected into that window. Next, a second window
6900 * appears. Since the first window is slippery, touch will move from the first window to the second.
6901 */
6902TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6903 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6904 sp<FakeWindowHandle> originalWindow =
6905 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6906 originalWindow->setFrame(Rect(0, 0, 200, 200));
6907 originalWindow->setSlippery(true);
6908
6909 sp<FakeWindowHandle> appearingWindow =
6910 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6911 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6912
6913 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6914
6915 // Touch down on the original window
6916 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6917 injectMotionEvent(*mDispatcher,
6918 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6919 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6920 .build()));
6921 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6922
6923 // Now, a new window appears. This could be, for example, a notification shade that appears
6924 // after user starts to drag down on the launcher window.
6925 mDispatcher->onWindowInfosChanged(
6926 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6927 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6928 injectMotionEvent(*mDispatcher,
6929 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6930 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6931 .build()));
6932 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6933 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6934 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6935 injectMotionEvent(*mDispatcher,
6936 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6937 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6938 .build()));
6939 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6940
6941 originalWindow->assertNoEvents();
6942 appearingWindow->assertNoEvents();
6943}
6944
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006945TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006946 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006947 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6948
6949 sp<FakeWindowHandle> leftWindow =
6950 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6951 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006952 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006953
6954 sp<FakeWindowHandle> rightSpy =
6955 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6956 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006957 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006958 rightSpy->setSpy(true);
6959 rightSpy->setTrustedOverlay(true);
6960
6961 sp<FakeWindowHandle> rightWindow =
6962 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6963 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006964 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006965
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006966 mDispatcher->onWindowInfosChanged(
6967 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006968
6969 // Touch in the left window
6970 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6971 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6972 .build());
6973 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6974 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006975 ASSERT_NO_FATAL_FAILURE(
6976 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006977
6978 // Touch another finger over the right windows
6979 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6980 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6981 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6982 .build());
6983 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6984 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6985 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6986 mDispatcher->waitForIdle();
6987 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006988 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6989 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006990
6991 // Release finger over left window. The UP actions are not treated as device interaction.
6992 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6993 // is part of the UP action, we do not treat this as device interaction.
6994 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6995 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6996 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6997 .build());
6998 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6999 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
7000 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
7001 mDispatcher->waitForIdle();
7002 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7003
7004 // Move remaining finger
7005 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7006 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7007 .build());
7008 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
7009 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
7010 mDispatcher->waitForIdle();
7011 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007012 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007013
7014 // Release all fingers
7015 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7016 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7017 .build());
7018 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
7019 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
7020 mDispatcher->waitForIdle();
7021 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7022}
7023
7024TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
7025 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7026
7027 sp<FakeWindowHandle> window =
7028 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
7029 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007030 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007031
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007032 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007033 setFocusedWindow(window);
7034 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
7035
7036 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
7037 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
7038 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007039 ASSERT_NO_FATAL_FAILURE(
7040 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007041
7042 // The UP actions are not treated as device interaction.
7043 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
7044 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
7045 mDispatcher->waitForIdle();
7046 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7047}
7048
Prabir Pradhan5893d362023-11-17 04:30:40 +00007049TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
7050 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7051
7052 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
7053 ADISPLAY_ID_DEFAULT);
7054 left->setFrame(Rect(0, 0, 100, 100));
7055 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
7056 "Right Window", ADISPLAY_ID_DEFAULT);
7057 right->setFrame(Rect(100, 0, 200, 100));
7058 sp<FakeWindowHandle> spy =
7059 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
7060 spy->setFrame(Rect(0, 0, 200, 100));
7061 spy->setTrustedOverlay(true);
7062 spy->setSpy(true);
7063
7064 mDispatcher->onWindowInfosChanged(
7065 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
7066
7067 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
7068 NotifyMotionArgs notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
7069 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
7070 mDispatcher->notifyMotion(notifyArgs);
7071
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007072 std::unique_ptr<MotionEvent> leftEnter = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00007073 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
7074 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007075 ASSERT_NE(nullptr, leftEnter);
Prabir Pradhan5893d362023-11-17 04:30:40 +00007076 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
7077 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007078 Not(WithEventId(leftEnter->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00007079 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
7080
7081 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
7082 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
7083 {PointF{150, 50}});
7084 mDispatcher->notifyMotion(notifyArgs);
7085
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007086 std::unique_ptr<MotionEvent> leftExit = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00007087 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
7088 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007089 ASSERT_NE(nullptr, leftExit);
Prabir Pradhan5893d362023-11-17 04:30:40 +00007090 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
7091 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007092 Not(WithEventId(leftExit->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00007093 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
7094
7095 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
7096}
7097
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00007098class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
7099protected:
7100 std::shared_ptr<FakeApplicationHandle> mApp;
7101 sp<FakeWindowHandle> mWindow;
7102
7103 virtual void SetUp() override {
7104 InputDispatcherTest::SetUp();
7105
7106 mApp = std::make_shared<FakeApplicationHandle>();
7107
7108 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
7109 mWindow->setFrame(Rect(0, 0, 100, 100));
7110
7111 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
7112 setFocusedWindow(mWindow);
7113 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
7114 }
7115
7116 void setFallback(int32_t keycode) {
7117 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
7118 return KeyEventBuilder(event).keyCode(keycode).build();
7119 });
7120 }
7121
7122 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007123 std::unique_ptr<KeyEvent> event = mWindow->consumeKey(handled);
7124 ASSERT_NE(nullptr, event);
7125 ASSERT_THAT(*event, matcher);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00007126 }
7127};
7128
7129TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
7130 mDispatcher->notifyKey(
7131 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7132 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
7133 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7134}
7135
7136TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
7137 mDispatcher->notifyKey(
7138 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7139 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
7140 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7141}
7142
7143TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
7144 mDispatcher->notifyKey(
7145 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7146
7147 // Do not handle this key event.
7148 consumeKey(/*handled=*/false,
7149 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7150 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7151
7152 // Since the policy did not request any fallback to be generated, ensure there are no events.
7153 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7154}
7155
7156TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
7157 setFallback(AKEYCODE_B);
7158 mDispatcher->notifyKey(
7159 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7160
7161 // Do not handle this key event.
7162 consumeKey(/*handled=*/false,
7163 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7164
7165 // Since the key was not handled, ensure the fallback event was dispatched instead.
7166 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7167 consumeKey(/*handled=*/true,
7168 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7169 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7170
7171 // Release the original key, and ensure the fallback key is also released.
7172 mDispatcher->notifyKey(
7173 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7174 consumeKey(/*handled=*/false,
7175 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7176 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7177 consumeKey(/*handled=*/true,
7178 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7179 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7180
7181 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7182 mWindow->assertNoEvents();
7183}
7184
7185TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
7186 setFallback(AKEYCODE_B);
7187 mDispatcher->notifyKey(
7188 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7189
7190 // Do not handle this key event, but handle the fallback.
7191 consumeKey(/*handled=*/false,
7192 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7193 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7194 consumeKey(/*handled=*/true,
7195 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7196 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7197
7198 // Release the original key, and ensure the fallback key is also released.
7199 mDispatcher->notifyKey(
7200 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7201 // But this time, the app handles the original key.
7202 consumeKey(/*handled=*/true,
7203 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7204 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7205 // Ensure the fallback key is canceled.
7206 consumeKey(/*handled=*/true,
7207 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7208 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7209
7210 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7211 mWindow->assertNoEvents();
7212}
7213
7214TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
7215 setFallback(AKEYCODE_B);
7216 mDispatcher->notifyKey(
7217 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7218
7219 // Do not handle this key event.
7220 consumeKey(/*handled=*/false,
7221 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7222 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7223 // App does not handle the fallback either, so ensure another fallback is not generated.
7224 setFallback(AKEYCODE_C);
7225 consumeKey(/*handled=*/false,
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 setFallback(AKEYCODE_B);
7231 mDispatcher->notifyKey(
7232 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7233 consumeKey(/*handled=*/false,
7234 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7235 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7236 consumeKey(/*handled=*/false,
7237 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7238 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7239
7240 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7241 mWindow->assertNoEvents();
7242}
7243
7244TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
7245 setFallback(AKEYCODE_B);
7246 mDispatcher->notifyKey(
7247 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7248
7249 // Do not handle this key event, so fallback is generated.
7250 consumeKey(/*handled=*/false,
7251 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7252 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7253 consumeKey(/*handled=*/true,
7254 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7255 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7256
7257 // Release the original key, but assume the policy is misbehaving and it
7258 // generates an inconsistent fallback to the one from the DOWN event.
7259 setFallback(AKEYCODE_C);
7260 mDispatcher->notifyKey(
7261 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7262 consumeKey(/*handled=*/false,
7263 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7264 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7265 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
7266 consumeKey(/*handled=*/true,
7267 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7268 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7269
7270 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7271 mWindow->assertNoEvents();
7272}
7273
7274TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
7275 setFallback(AKEYCODE_B);
7276 mDispatcher->notifyKey(
7277 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7278
7279 // Do not handle this key event, so fallback is generated.
7280 consumeKey(/*handled=*/false,
7281 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7282 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7283 consumeKey(/*handled=*/true,
7284 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7285 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7286
7287 // The original key is canceled.
7288 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
7289 .keyCode(AKEYCODE_A)
7290 .addFlag(AKEY_EVENT_FLAG_CANCELED)
7291 .build());
7292 consumeKey(/*handled=*/false,
7293 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
7294 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7295 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7296 // Ensure the fallback key is also canceled due to the original key being canceled.
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
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00007305TEST_F(InputDispatcherFallbackKeyTest, InputChannelRemovedDuringPolicyCall) {
Prabir Pradhanb13da8f2024-01-09 23:10:13 +00007306 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.
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 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
7319 // When the unhandled key is reported to the policy next, remove the input channel.
7320 mDispatcher->removeInputChannel(mWindow->getToken());
7321 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
7322 });
7323 // Release the original key, and let the app now handle the previously unhandled key.
7324 // This should result in the previously generated fallback key to be cancelled.
7325 // Since the policy was notified of the unhandled DOWN event earlier, it will also be notified
7326 // of the UP event for consistency. The Dispatcher calls into the policy from its own thread
7327 // without holding the lock, because it need to synchronously fetch the fallback key. While in
7328 // the policy call, we will now remove the input channel. Once the policy call returns, the
7329 // Dispatcher will no longer have a channel to send cancellation events to. Ensure this does
7330 // not cause any crashes.
7331 mDispatcher->notifyKey(
7332 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7333 consumeKey(/*handled=*/true,
7334 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7335 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7336}
7337
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00007338TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedDuringPolicyCall) {
7339 setFallback(AKEYCODE_B);
7340 mDispatcher->notifyKey(
7341 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7342
7343 // Do not handle this key event.
7344 consumeKey(/*handled=*/false,
7345 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7346 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7347 consumeKey(/*handled=*/true,
7348 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7349 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7350
7351 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
7352 // When the unhandled key is reported to the policy next, remove the window.
7353 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
7354 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
7355 });
7356 // Release the original key, which the app will not handle. When this unhandled key is reported
7357 // to the policy, the window will be removed.
7358 mDispatcher->notifyKey(
7359 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7360 consumeKey(/*handled=*/false,
7361 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7362 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7363
7364 // Since the window was removed, it loses focus, and the channel state will be reset.
7365 consumeKey(/*handled=*/true,
7366 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7367 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7368 mWindow->consumeFocusEvent(false);
7369 mWindow->assertNoEvents();
7370}
7371
7372TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedWhileAwaitingFinishedSignal) {
7373 setFallback(AKEYCODE_B);
7374 mDispatcher->notifyKey(
7375 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7376
7377 // Do not handle this key event.
7378 consumeKey(/*handled=*/false,
7379 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7380 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7381 const auto [seq, event] = mWindow->receiveEvent();
7382 ASSERT_TRUE(seq.has_value() && event != nullptr) << "Failed to receive fallback event";
7383 ASSERT_EQ(event->getType(), InputEventType::KEY);
7384 ASSERT_THAT(static_cast<const KeyEvent&>(*event),
7385 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7386 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7387
7388 // Remove the window now, which should generate a cancellations and make the window lose focus.
7389 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
7390 consumeKey(/*handled=*/true,
7391 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
7392 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7393 consumeKey(/*handled=*/true,
7394 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7395 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7396 mWindow->consumeFocusEvent(false);
7397
7398 // Finish the event by reporting it as handled.
7399 mWindow->finishEvent(*seq);
7400 mWindow->assertNoEvents();
7401}
7402
Garfield Tan1c7bc862020-01-28 13:24:04 -08007403class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
7404protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08007405 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
7406 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007407
Chris Yea209fde2020-07-22 13:54:51 -07007408 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007409 sp<FakeWindowHandle> mWindow;
7410
7411 virtual void SetUp() override {
Prabir Pradhandae52792023-12-15 07:36:40 +00007412 InputDispatcherTest::SetUp();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007413
Prabir Pradhandae52792023-12-15 07:36:40 +00007414 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007415 setUpWindow();
7416 }
7417
7418 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07007419 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007420 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007421
Vishnu Nair47074b82020-08-14 11:54:47 -07007422 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007423 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007424 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007425 mWindow->consumeFocusEvent(true);
7426 }
7427
Chris Ye2ad95392020-09-01 13:44:44 -07007428 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007429 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007430 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007431 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007432 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007433
7434 // Window should receive key down event.
7435 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7436 }
7437
7438 void expectKeyRepeatOnce(int32_t repeatCount) {
7439 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007440 mWindow->consumeKeyEvent(
7441 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007442 }
7443
Chris Ye2ad95392020-09-01 13:44:44 -07007444 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007445 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007446 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007447 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007448 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007449
7450 // Window should receive key down event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007451 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007452 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007453 }
7454};
7455
7456TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00007457 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007458 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7459 expectKeyRepeatOnce(repeatCount);
7460 }
7461}
7462
7463TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00007464 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007465 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7466 expectKeyRepeatOnce(repeatCount);
7467 }
Harry Cutts33476232023-01-30 19:57:29 +00007468 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007469 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08007470 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7471 expectKeyRepeatOnce(repeatCount);
7472 }
7473}
7474
7475TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007476 sendAndConsumeKeyDown(/*deviceId=*/1);
7477 expectKeyRepeatOnce(/*repeatCount=*/1);
7478 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007479 mWindow->assertNoEvents();
7480}
7481
7482TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007483 sendAndConsumeKeyDown(/*deviceId=*/1);
7484 expectKeyRepeatOnce(/*repeatCount=*/1);
7485 sendAndConsumeKeyDown(/*deviceId=*/2);
7486 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007487 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00007488 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007489 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00007490 expectKeyRepeatOnce(/*repeatCount=*/2);
7491 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07007492 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00007493 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007494 mWindow->assertNoEvents();
7495}
7496
7497TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007498 sendAndConsumeKeyDown(/*deviceId=*/1);
7499 expectKeyRepeatOnce(/*repeatCount=*/1);
7500 sendAndConsumeKeyDown(/*deviceId=*/2);
7501 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007502 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00007503 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007504 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08007505 mWindow->assertNoEvents();
7506}
7507
liushenxiang42232912021-05-21 20:24:09 +08007508TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
7509 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00007510 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007511 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08007512 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
7513 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
7514 mWindow->assertNoEvents();
7515}
7516
Garfield Tan1c7bc862020-01-28 13:24:04 -08007517TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007518 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007519 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007520 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007521 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
7522 ASSERT_NE(nullptr, repeatEvent);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007523 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007524 IdGenerator::getSource(repeatEvent->getId()));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007525 }
7526}
7527
7528TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007529 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007530 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007531
7532 std::unordered_set<int32_t> idSet;
7533 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007534 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
7535 ASSERT_NE(nullptr, repeatEvent);
7536 int32_t id = repeatEvent->getId();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007537 EXPECT_EQ(idSet.end(), idSet.find(id));
7538 idSet.insert(id);
7539 }
7540}
7541
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007542/* Test InputDispatcher for MultiDisplay */
7543class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
7544public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007545 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007546 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08007547
Chris Yea209fde2020-07-22 13:54:51 -07007548 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007549 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007550 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007551
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007552 // Set focus window for primary display, but focused display would be second one.
7553 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07007554 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007555 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
7556
Vishnu Nair958da932020-08-21 17:12:37 -07007557 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007558 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08007559
Chris Yea209fde2020-07-22 13:54:51 -07007560 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007561 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007562 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007563 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007564 // Set focus display to second one.
7565 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
7566 // Set focus window for second display.
7567 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07007568 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007569 mDispatcher->onWindowInfosChanged(
7570 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007571 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007572 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007573 }
7574
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007575 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007576 InputDispatcherTest::TearDown();
7577
Chris Yea209fde2020-07-22 13:54:51 -07007578 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007579 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07007580 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007581 windowInSecondary.clear();
7582 }
7583
7584protected:
Chris Yea209fde2020-07-22 13:54:51 -07007585 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007586 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07007587 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007588 sp<FakeWindowHandle> windowInSecondary;
7589};
7590
7591TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
7592 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007593 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007594 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007595 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007596 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08007597 windowInSecondary->assertNoEvents();
7598
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007599 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007600 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007601 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007602 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007603 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007604 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08007605}
7606
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007607TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08007608 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007609 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007610 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007611 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007612 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08007613 windowInSecondary->assertNoEvents();
7614
7615 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007616 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007617 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007618 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007619 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08007620
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007621 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007622 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08007623
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007624 // Old focus should receive a cancel event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007625 windowInSecondary->consumeKeyUp(ADISPLAY_ID_NONE, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08007626
7627 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007628 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08007629 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007630 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08007631 windowInSecondary->assertNoEvents();
7632}
7633
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007634// Test per-display input monitors for motion event.
7635TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08007636 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007637 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007638 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007639 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007640
7641 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007643 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007644 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007645 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007646 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007647 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007648 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007649
7650 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007651 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007652 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007653 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007654 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007655 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007656 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08007657 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007658
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007659 // Lift up the touch from the second display
7660 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007661 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007662 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7663 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
7664 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
7665
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007666 // Test inject a non-pointer motion event.
7667 // If specific a display, it will dispatch to the focused window of particular display,
7668 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007669 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007670 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007671 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007672 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007673 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007674 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007675 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007676}
7677
7678// Test per-display input monitors for key event.
7679TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007680 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08007681 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007682 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007683 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007684 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007685
7686 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007687 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007688 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007689 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007690 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007691 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007692 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007693}
7694
Vishnu Nair958da932020-08-21 17:12:37 -07007695TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
7696 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007697 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007698 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007699 mDispatcher->onWindowInfosChanged(
7700 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
7701 *windowInSecondary->getInfo()},
7702 {},
7703 0,
7704 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007705 setFocusedWindow(secondWindowInPrimary);
7706 windowInPrimary->consumeFocusEvent(false);
7707 secondWindowInPrimary->consumeFocusEvent(true);
7708
7709 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007710 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7711 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007712 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007713 windowInPrimary->assertNoEvents();
7714 windowInSecondary->assertNoEvents();
7715 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7716}
7717
Arthur Hungdfd528e2021-12-08 13:23:04 +00007718TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
7719 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007720 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007721 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007722 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007723
7724 // Test touch down on primary display.
7725 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007726 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007727 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7728 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7729 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
7730
7731 // Test touch down on second display.
7732 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007733 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007734 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7735 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
7736 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
7737
7738 // Trigger cancel touch.
7739 mDispatcher->cancelCurrentTouch();
7740 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7741 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7742 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
7743 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
7744
7745 // Test inject a move motion event, no window/monitor should receive the event.
7746 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007747 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007748 ADISPLAY_ID_DEFAULT, {110, 200}))
7749 << "Inject motion event should return InputEventInjectionResult::FAILED";
7750 windowInPrimary->assertNoEvents();
7751 monitorInPrimary.assertNoEvents();
7752
7753 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007754 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007755 SECOND_DISPLAY_ID, {110, 200}))
7756 << "Inject motion event should return InputEventInjectionResult::FAILED";
7757 windowInSecondary->assertNoEvents();
7758 monitorInSecondary.assertNoEvents();
7759}
7760
Hu Guocb134f12023-12-23 13:42:44 +00007761/**
7762 * Send a key to the primary display and to the secondary display.
7763 * Then cause the key on the primary display to be canceled by sending in a stale key.
7764 * Ensure that the key on the primary display is canceled, and that the key on the secondary display
7765 * does not get canceled.
7766 */
7767TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture) {
7768 // Send a key down on primary display
7769 mDispatcher->notifyKey(
7770 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7771 .displayId(ADISPLAY_ID_DEFAULT)
7772 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7773 .build());
7774 windowInPrimary->consumeKeyEvent(
7775 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7776 windowInSecondary->assertNoEvents();
7777
7778 // Send a key down on second display
7779 mDispatcher->notifyKey(
7780 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7781 .displayId(SECOND_DISPLAY_ID)
7782 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7783 .build());
7784 windowInSecondary->consumeKeyEvent(
7785 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7786 windowInPrimary->assertNoEvents();
7787
7788 // Send a valid key up event on primary display that will be dropped because it is stale
7789 NotifyKeyArgs staleKeyUp =
7790 KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
7791 .displayId(ADISPLAY_ID_DEFAULT)
7792 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7793 .build();
7794 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7795 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7796 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7797 mDispatcher->notifyKey(staleKeyUp);
7798
7799 // Only the key gesture corresponding to the dropped event should receive the cancel event.
7800 // Therefore, windowInPrimary should get the cancel event and windowInSecondary should not
7801 // receive any events.
7802 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
7803 WithDisplayId(ADISPLAY_ID_DEFAULT),
7804 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7805 windowInSecondary->assertNoEvents();
7806}
7807
7808/**
7809 * Similar to 'WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture' but for motion events.
7810 */
7811TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropMotionEvent_OnlyCancelCorrespondingGesture) {
7812 // Send touch down on primary display.
7813 mDispatcher->notifyMotion(
7814 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7815 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7816 .displayId(ADISPLAY_ID_DEFAULT)
7817 .build());
7818 windowInPrimary->consumeMotionEvent(
7819 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7820 windowInSecondary->assertNoEvents();
7821
7822 // Send touch down on second display.
7823 mDispatcher->notifyMotion(
7824 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7825 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7826 .displayId(SECOND_DISPLAY_ID)
7827 .build());
7828 windowInPrimary->assertNoEvents();
7829 windowInSecondary->consumeMotionEvent(
7830 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7831
7832 // inject a valid MotionEvent on primary display that will be stale when it arrives.
7833 NotifyMotionArgs staleMotionUp =
7834 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7835 .displayId(ADISPLAY_ID_DEFAULT)
7836 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7837 .build();
7838 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7839 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7840 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7841 mDispatcher->notifyMotion(staleMotionUp);
7842
7843 // For stale motion events, we let the gesture to complete. This behaviour is different from key
7844 // events, where we would cancel the current keys instead.
7845 windowInPrimary->consumeMotionEvent(WithMotionAction(ACTION_UP));
7846 windowInSecondary->assertNoEvents();
7847}
7848
Jackal Guof9696682018-10-05 12:23:23 +08007849class InputFilterTest : public InputDispatcherTest {
7850protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007851 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
7852 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08007853 NotifyMotionArgs motionArgs;
7854
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007855 motionArgs =
7856 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007857 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007858 motionArgs =
7859 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007860 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007861 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007862 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007863 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007864 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08007865 } else {
7866 mFakePolicy->assertFilterInputEventWasNotCalled();
7867 }
7868 }
7869
7870 void testNotifyKey(bool expectToBeFiltered) {
7871 NotifyKeyArgs keyArgs;
7872
7873 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007874 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007875 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007876 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007877 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007878
7879 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08007880 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007881 } else {
7882 mFakePolicy->assertFilterInputEventWasNotCalled();
7883 }
7884 }
7885};
7886
7887// Test InputFilter for MotionEvent
7888TEST_F(InputFilterTest, MotionEvent_InputFilter) {
7889 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007890 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7891 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007892
7893 // Enable InputFilter
7894 mDispatcher->setInputFilterEnabled(true);
7895 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007896 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
7897 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007898
7899 // Disable InputFilter
7900 mDispatcher->setInputFilterEnabled(false);
7901 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007902 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7903 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007904}
7905
7906// Test InputFilter for KeyEvent
7907TEST_F(InputFilterTest, KeyEvent_InputFilter) {
7908 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007909 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007910
7911 // Enable InputFilter
7912 mDispatcher->setInputFilterEnabled(true);
7913 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007914 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007915
7916 // Disable InputFilter
7917 mDispatcher->setInputFilterEnabled(false);
7918 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007919 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007920}
7921
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007922// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
7923// logical display coordinate space.
7924TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
7925 ui::Transform firstDisplayTransform;
7926 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7927 ui::Transform secondDisplayTransform;
7928 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
7929
7930 std::vector<gui::DisplayInfo> displayInfos(2);
7931 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
7932 displayInfos[0].transform = firstDisplayTransform;
7933 displayInfos[1].displayId = SECOND_DISPLAY_ID;
7934 displayInfos[1].transform = secondDisplayTransform;
7935
Patrick Williamsd828f302023-04-28 17:52:08 -05007936 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007937
7938 // Enable InputFilter
7939 mDispatcher->setInputFilterEnabled(true);
7940
7941 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007942 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
7943 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007944}
7945
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007946class InputFilterInjectionPolicyTest : public InputDispatcherTest {
7947protected:
7948 virtual void SetUp() override {
7949 InputDispatcherTest::SetUp();
7950
7951 /**
7952 * We don't need to enable input filter to test the injected event policy, but we enabled it
7953 * here to make the tests more realistic, since this policy only matters when inputfilter is
7954 * on.
7955 */
7956 mDispatcher->setInputFilterEnabled(true);
7957
7958 std::shared_ptr<InputApplicationHandle> application =
7959 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007960 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
7961 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007962
7963 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7964 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007965 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007966 setFocusedWindow(mWindow);
7967 mWindow->consumeFocusEvent(true);
7968 }
7969
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007970 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7971 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007972 KeyEvent event;
7973
7974 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7975 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
7976 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00007977 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007978 const int32_t additionalPolicyFlags =
7979 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
7980 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007981 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007982 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007983 policyFlags | additionalPolicyFlags));
7984
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007985 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007986 }
7987
7988 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7989 int32_t flags) {
7990 MotionEvent event;
7991 PointerProperties pointerProperties[1];
7992 PointerCoords pointerCoords[1];
7993 pointerProperties[0].clear();
7994 pointerProperties[0].id = 0;
7995 pointerCoords[0].clear();
7996 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
7997 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
7998
7999 ui::Transform identityTransform;
8000 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
8001 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
8002 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
8003 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
8004 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07008005 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07008006 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00008007 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008008
8009 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
8010 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00008011 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00008012 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008013 policyFlags | additionalPolicyFlags));
8014
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008015 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008016 }
8017
8018private:
8019 sp<FakeWindowHandle> mWindow;
8020};
8021
8022TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008023 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
8024 // filter. Without it, the event will no different from a regularly injected event, and the
8025 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00008026 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
8027 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008028}
8029
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008030TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008031 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00008032 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008033 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
8034}
8035
8036TEST_F(InputFilterInjectionPolicyTest,
8037 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
8038 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00008039 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008040 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008041}
8042
8043TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00008044 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
8045 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008046}
8047
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08008048class InputDispatcherUserActivityPokeTests : public InputDispatcherTest {
8049protected:
8050 virtual void SetUp() override {
8051 InputDispatcherTest::SetUp();
8052
8053 std::shared_ptr<FakeApplicationHandle> application =
8054 std::make_shared<FakeApplicationHandle>();
8055 application->setDispatchingTimeout(100ms);
8056 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
8057 ADISPLAY_ID_DEFAULT);
Yeabkal Wubshit222d83d2024-01-24 18:00:09 +00008058 mWindow->setFrame(Rect(0, 0, 100, 100));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08008059 mWindow->setDispatchingTimeout(100ms);
8060 mWindow->setFocusable(true);
8061
8062 // Set focused application.
8063 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8064
8065 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
8066 setFocusedWindow(mWindow);
8067 mWindow->consumeFocusEvent(true);
8068 }
8069
8070 void notifyAndConsumeMotion(int32_t action, uint32_t source, int32_t displayId,
8071 nsecs_t eventTime) {
8072 mDispatcher->notifyMotion(MotionArgsBuilder(action, source)
8073 .displayId(displayId)
8074 .eventTime(eventTime)
8075 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8076 .build());
8077 mWindow->consumeMotionEvent(WithMotionAction(action));
8078 }
8079
8080private:
8081 sp<FakeWindowHandle> mWindow;
8082};
8083
8084TEST_F_WITH_FLAGS(
8085 InputDispatcherUserActivityPokeTests, MinPokeTimeObserved,
8086 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8087 rate_limit_user_activity_poke_in_dispatcher))) {
8088 mDispatcher->setMinTimeBetweenUserActivityPokes(50ms);
8089
8090 // First event of type TOUCH. Should poke.
8091 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8092 milliseconds_to_nanoseconds(50));
8093 mFakePolicy->assertUserActivityPoked(
8094 {{milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8095
8096 // 80ns > 50ns has passed since previous TOUCH event. Should poke.
8097 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8098 milliseconds_to_nanoseconds(130));
8099 mFakePolicy->assertUserActivityPoked(
8100 {{milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8101
8102 // First event of type OTHER. Should poke (despite being within 50ns of previous TOUCH event).
8103 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8104 milliseconds_to_nanoseconds(135));
8105 mFakePolicy->assertUserActivityPoked(
8106 {{milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER, ADISPLAY_ID_DEFAULT}});
8107
8108 // Within 50ns of previous TOUCH event. Should NOT poke.
8109 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8110 milliseconds_to_nanoseconds(140));
8111 mFakePolicy->assertUserActivityNotPoked();
8112
8113 // Within 50ns of previous OTHER event. Should NOT poke.
8114 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8115 milliseconds_to_nanoseconds(150));
8116 mFakePolicy->assertUserActivityNotPoked();
8117
8118 // Within 50ns of previous TOUCH event (which was at time 130). Should NOT poke.
8119 // Note that STYLUS is mapped to TOUCH user activity, since it's a pointer-type source.
8120 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
8121 milliseconds_to_nanoseconds(160));
8122 mFakePolicy->assertUserActivityNotPoked();
8123
8124 // 65ns > 50ns has passed since previous OTHER event. Should poke.
8125 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8126 milliseconds_to_nanoseconds(200));
8127 mFakePolicy->assertUserActivityPoked(
8128 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER, ADISPLAY_ID_DEFAULT}});
8129
8130 // 170ns > 50ns has passed since previous TOUCH event. Should poke.
8131 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
8132 milliseconds_to_nanoseconds(300));
8133 mFakePolicy->assertUserActivityPoked(
8134 {{milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8135
8136 // Assert that there's no more user activity poke event.
8137 mFakePolicy->assertUserActivityNotPoked();
8138}
8139
8140TEST_F_WITH_FLAGS(
8141 InputDispatcherUserActivityPokeTests, DefaultMinPokeTimeOf100MsUsed,
8142 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8143 rate_limit_user_activity_poke_in_dispatcher))) {
8144 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8145 milliseconds_to_nanoseconds(200));
8146 mFakePolicy->assertUserActivityPoked(
8147 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8148
8149 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8150 milliseconds_to_nanoseconds(280));
8151 mFakePolicy->assertUserActivityNotPoked();
8152
8153 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8154 milliseconds_to_nanoseconds(340));
8155 mFakePolicy->assertUserActivityPoked(
8156 {{milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8157}
8158
8159TEST_F_WITH_FLAGS(
8160 InputDispatcherUserActivityPokeTests, ZeroMinPokeTimeDisablesRateLimiting,
8161 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8162 rate_limit_user_activity_poke_in_dispatcher))) {
8163 mDispatcher->setMinTimeBetweenUserActivityPokes(0ms);
8164
8165 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20);
8166 mFakePolicy->assertUserActivityPoked();
8167
8168 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 30);
8169 mFakePolicy->assertUserActivityPoked();
8170}
8171
chaviwfd6d3512019-03-25 13:23:49 -07008172class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008173 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07008174 InputDispatcherTest::SetUp();
8175
Chris Yea209fde2020-07-22 13:54:51 -07008176 std::shared_ptr<FakeApplicationHandle> application =
8177 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008178 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008179 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07008180 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07008181
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008182 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008183 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008184 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07008185
8186 // Set focused application.
8187 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07008188 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07008189
8190 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008191 mDispatcher->onWindowInfosChanged(
8192 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008193 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008194 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07008195 }
8196
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008197 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07008198 InputDispatcherTest::TearDown();
8199
8200 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008201 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07008202 }
8203
8204protected:
8205 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008206 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008207 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07008208};
8209
8210// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
8211// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
8212// the onPointerDownOutsideFocus callback.
8213TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008214 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008215 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008216 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008217 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008218 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008219
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008220 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07008221 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
8222}
8223
8224// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
8225// DOWN on the window that doesn't have focus. Ensure no window received the
8226// onPointerDownOutsideFocus callback.
8227TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008228 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008229 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
8230 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008231 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008232 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008233
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008234 ASSERT_TRUE(mDispatcher->waitForIdle());
8235 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008236}
8237
8238// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
8239// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
8240TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08008241 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008242 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008243 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008244 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07008245
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008246 ASSERT_TRUE(mDispatcher->waitForIdle());
8247 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008248}
8249
8250// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
8251// DOWN on the window that already has focus. Ensure no window received the
8252// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008253TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008254 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008255 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008256 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008257 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008258 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008259
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008260 ASSERT_TRUE(mDispatcher->waitForIdle());
8261 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008262}
8263
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008264// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
8265// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
8266TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
8267 const MotionEvent event =
8268 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
8269 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008270 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008271 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
8272 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008273 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008274 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8275 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
8276
8277 ASSERT_TRUE(mDispatcher->waitForIdle());
8278 mFakePolicy->assertOnPointerDownWasNotCalled();
8279 // Ensure that the unfocused window did not receive any FOCUS events.
8280 mUnfocusedWindow->assertNoEvents();
8281}
8282
chaviwaf87b3e2019-10-01 16:59:28 -07008283// These tests ensures we can send touch events to a single client when there are multiple input
8284// windows that point to the same client token.
8285class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
8286 virtual void SetUp() override {
8287 InputDispatcherTest::SetUp();
8288
Chris Yea209fde2020-07-22 13:54:51 -07008289 std::shared_ptr<FakeApplicationHandle> application =
8290 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008291 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
8292 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07008293 mWindow1->setFrame(Rect(0, 0, 100, 100));
8294
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00008295 mWindow2 = mWindow1->clone(ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07008296 mWindow2->setFrame(Rect(100, 100, 200, 200));
8297
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008298 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07008299 }
8300
8301protected:
8302 sp<FakeWindowHandle> mWindow1;
8303 sp<FakeWindowHandle> mWindow2;
8304
8305 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05008306 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07008307 vec2 vals = windowInfo->transform.transform(point.x, point.y);
8308 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07008309 }
8310
8311 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
8312 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008313 const std::string name = window->getName();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008314 std::unique_ptr<MotionEvent> motionEvent =
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008315 window->consumeMotionEvent(WithMotionAction(expectedAction));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008316 ASSERT_NE(nullptr, motionEvent);
8317 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07008318
8319 for (size_t i = 0; i < points.size(); i++) {
8320 float expectedX = points[i].x;
8321 float expectedY = points[i].y;
8322
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008323 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07008324 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008325 << ", got " << motionEvent->getX(i);
8326 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07008327 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008328 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07008329 }
8330 }
chaviw9eaa22c2020-07-01 16:21:27 -07008331
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008332 void touchAndAssertPositions(sp<FakeWindowHandle> touchedWindow, int32_t action,
8333 const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07008334 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008335 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
8336 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07008337
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008338 consumeMotionEvent(touchedWindow, action, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008339 }
chaviwaf87b3e2019-10-01 16:59:28 -07008340};
8341
8342TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
8343 // Touch Window 1
8344 PointF touchedPoint = {10, 10};
8345 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008346 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008347
8348 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008349 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008350
8351 // Touch Window 2
8352 touchedPoint = {150, 150};
8353 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008354 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008355}
8356
chaviw9eaa22c2020-07-01 16:21:27 -07008357TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
8358 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07008359 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008360 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07008361
8362 // Touch Window 1
8363 PointF touchedPoint = {10, 10};
8364 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008365 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008366 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008367 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008368
8369 // Touch Window 2
8370 touchedPoint = {150, 150};
8371 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008372 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
8373 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008374
chaviw9eaa22c2020-07-01 16:21:27 -07008375 // Update the transform so rotation is set
8376 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008377 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008378 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008379 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008380}
8381
chaviw9eaa22c2020-07-01 16:21:27 -07008382TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008383 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008384 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008385
8386 // Touch Window 1
8387 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8388 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008389 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008390
8391 // Touch Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008392 // Since this is part of the same touch gesture that has already been dispatched to Window 1,
8393 // the touch stream from Window 2 will be merged with the stream in Window 1. The merged stream
8394 // will continue to be dispatched through Window 1.
chaviw9eaa22c2020-07-01 16:21:27 -07008395 touchedPoints.push_back(PointF{150, 150});
8396 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008397 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008398
chaviw9eaa22c2020-07-01 16:21:27 -07008399 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008400 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008401 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008402
chaviw9eaa22c2020-07-01 16:21:27 -07008403 // Update the transform so rotation is set for Window 2
8404 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008405 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008406 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008407 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008408}
8409
chaviw9eaa22c2020-07-01 16:21:27 -07008410TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008411 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008412 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008413
8414 // Touch Window 1
8415 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8416 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008417 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008418
8419 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07008420 touchedPoints.push_back(PointF{150, 150});
8421 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008422
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008423 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008424
8425 // Move both windows
8426 touchedPoints = {{20, 20}, {175, 175}};
8427 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8428 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8429
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008430 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008431
chaviw9eaa22c2020-07-01 16:21:27 -07008432 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008433 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008434 expectedPoints.pop_back();
8435
8436 // Touch Window 2
8437 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008438 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008439 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008440 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008441
8442 // Move both windows
8443 touchedPoints = {{20, 20}, {175, 175}};
8444 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8445 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8446
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008447 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008448}
8449
8450TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
8451 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008452 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008453
8454 // Touch Window 1
8455 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8456 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008457 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008458
8459 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07008460 touchedPoints.push_back(PointF{150, 150});
8461 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008462
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008463 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008464
8465 // Move both windows
8466 touchedPoints = {{20, 20}, {175, 175}};
8467 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8468 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8469
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008470 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008471}
8472
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07008473/**
8474 * When one of the windows is slippery, the touch should not slip into the other window with the
8475 * same input channel.
8476 */
8477TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
8478 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008479 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07008480
8481 // Touch down in window 1
8482 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8483 ADISPLAY_ID_DEFAULT, {{50, 50}}));
8484 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
8485
8486 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
8487 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
8488 // getting generated.
8489 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8490 ADISPLAY_ID_DEFAULT, {{150, 150}}));
8491
8492 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
8493}
8494
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008495/**
8496 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
8497 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
8498 * that the pointer is hovering over may have a different transform.
8499 */
8500TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008501 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008502
8503 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008504 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
8505 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8506 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008507 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
8508 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008509 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008510 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8511 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
8512 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008513 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008514 consumeMotionEvent(mWindow2, ACTION_HOVER_ENTER,
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008515 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
8516}
8517
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008518class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
8519 virtual void SetUp() override {
8520 InputDispatcherTest::SetUp();
8521
Chris Yea209fde2020-07-22 13:54:51 -07008522 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008523 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008524 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
8525 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008526 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008527 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07008528 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008529
8530 // Set focused application.
8531 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8532
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008533 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008534 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008535 mWindow->consumeFocusEvent(true);
8536 }
8537
8538 virtual void TearDown() override {
8539 InputDispatcherTest::TearDown();
8540 mWindow.clear();
8541 }
8542
8543protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008544 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07008545 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008546 sp<FakeWindowHandle> mWindow;
8547 static constexpr PointF WINDOW_LOCATION = {20, 20};
8548
8549 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008550 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
8551 .x(WINDOW_LOCATION.x)
8552 .y(WINDOW_LOCATION.y);
8553 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8554 .pointer(touchingPointer)
8555 .build());
8556 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8557 .pointer(touchingPointer)
8558 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008559 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008560
8561 sp<FakeWindowHandle> addSpyWindow() {
8562 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008563 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008564 spy->setTrustedOverlay(true);
8565 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008566 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008567 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008568 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008569 return spy;
8570 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008571};
8572
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008573// Send a tap and respond, which should not cause an ANR.
8574TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
8575 tapOnWindow();
8576 mWindow->consumeMotionDown();
8577 mWindow->consumeMotionUp();
8578 ASSERT_TRUE(mDispatcher->waitForIdle());
8579 mFakePolicy->assertNotifyAnrWasNotCalled();
8580}
8581
8582// Send a regular key and respond, which should not cause an ANR.
8583TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008584 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008585 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8586 ASSERT_TRUE(mDispatcher->waitForIdle());
8587 mFakePolicy->assertNotifyAnrWasNotCalled();
8588}
8589
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008590TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
8591 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008592 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008593 mWindow->consumeFocusEvent(false);
8594
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008595 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008596 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8597 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00008598 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008599 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008600 // Key will not go to window because we have no focused window.
8601 // The 'no focused window' ANR timer should start instead.
8602
8603 // Now, the focused application goes away.
8604 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
8605 // The key should get dropped and there should be no ANR.
8606
8607 ASSERT_TRUE(mDispatcher->waitForIdle());
8608 mFakePolicy->assertNotifyAnrWasNotCalled();
8609}
8610
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008611// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008612// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8613// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008614TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008615 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008616 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008617 WINDOW_LOCATION));
8618
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008619 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008620 ASSERT_TRUE(sequenceNum);
8621 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008622 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008623
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008624 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008625 mWindow->consumeMotionEvent(
8626 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008627 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008628 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008629}
8630
8631// Send a key to the app and have the app not respond right away.
8632TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
8633 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008634 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008635 const auto [sequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008636 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008637 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008638 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008639 ASSERT_TRUE(mDispatcher->waitForIdle());
8640}
8641
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008642// We have a focused application, but no focused window
8643TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008644 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008645 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008646 mWindow->consumeFocusEvent(false);
8647
8648 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008649 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008650 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008651 WINDOW_LOCATION));
8652 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
8653 mDispatcher->waitForIdle();
8654 mFakePolicy->assertNotifyAnrWasNotCalled();
8655
8656 // Once a focused event arrives, we get an ANR for this application
8657 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8658 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008659 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008660 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008661 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008662 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008663 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07008664 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008665 ASSERT_TRUE(mDispatcher->waitForIdle());
8666}
8667
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008668/**
8669 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
8670 * there will not be an ANR.
8671 */
8672TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
8673 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008674 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008675 mWindow->consumeFocusEvent(false);
8676
8677 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07008678 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
8679 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008680 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
8681 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
8682
8683 // Define a valid key down event that is stale (too old).
8684 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00008685 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00008686 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008687
8688 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
8689
8690 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00008691 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008692 InputEventInjectionSync::WAIT_FOR_RESULT,
8693 INJECT_EVENT_TIMEOUT, policyFlags);
8694 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
8695 << "Injection should fail because the event is stale";
8696
8697 ASSERT_TRUE(mDispatcher->waitForIdle());
8698 mFakePolicy->assertNotifyAnrWasNotCalled();
8699 mWindow->assertNoEvents();
8700}
8701
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008702// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008703// Make sure that we don't notify policy twice about the same ANR.
8704TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008705 const std::chrono::duration appTimeout = 400ms;
8706 mApplication->setDispatchingTimeout(appTimeout);
8707 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8708
Vishnu Nair47074b82020-08-14 11:54:47 -07008709 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008710 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008711 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008712
8713 // Once a focused event arrives, we get an ANR for this application
8714 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8715 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008716 const std::chrono::duration eventInjectionTimeout = 100ms;
8717 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008718 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008719 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008720 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
8721 /*allowKeyRepeat=*/false);
8722 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
8723 << "result=" << ftl::enum_string(result);
8724 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
8725 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
8726 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
8727 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008728
Vishnu Naire4df8752022-09-08 09:17:55 -07008729 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008730 // ANR should not be raised again. It is up to policy to do that if it desires.
8731 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008732
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008733 // If we now get a focused window, the ANR should stop, but the policy handles that via
8734 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008735 ASSERT_TRUE(mDispatcher->waitForIdle());
8736}
8737
8738// We have a focused application, but no focused window
8739TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008740 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008741 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008742 mWindow->consumeFocusEvent(false);
8743
8744 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008745 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008746
Vishnu Naire4df8752022-09-08 09:17:55 -07008747 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8748 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008749
8750 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008751 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008752 ASSERT_TRUE(mDispatcher->waitForIdle());
8753 mWindow->assertNoEvents();
8754}
8755
8756/**
8757 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
8758 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
8759 * If we process 1 of the events, but ANR on the second event with the same timestamp,
8760 * the ANR mechanism should still work.
8761 *
8762 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
8763 * DOWN event, while not responding on the second one.
8764 */
8765TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
8766 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008767 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008768 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8769 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8770 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008771 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008772
8773 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008774 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008775 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8776 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8777 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008778 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008779
8780 // We have now sent down and up. Let's consume first event and then ANR on the second.
8781 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8782 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008783 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008784}
8785
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008786// A spy window can receive an ANR
8787TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
8788 sp<FakeWindowHandle> spy = addSpyWindow();
8789
8790 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008791 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008792 WINDOW_LOCATION));
8793 mWindow->consumeMotionDown();
8794
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008795 const auto [sequenceNum, _] = spy->receiveEvent(); // ACTION_DOWN
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008796 ASSERT_TRUE(sequenceNum);
8797 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008798 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008799
8800 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008801 spy->consumeMotionEvent(
8802 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008803 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008804 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008805}
8806
8807// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008808// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008809TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
8810 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008811
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008812 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008813 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008814 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008815 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008816
8817 // Stuck on the ACTION_UP
8818 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008819 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008820
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008821 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008822 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008823 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8824 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008825
8826 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8827 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008828 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008829 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008830 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008831}
8832
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008833// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008834// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008835TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
8836 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008837
8838 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008839 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8840 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008841
8842 mWindow->consumeMotionDown();
8843 // Stuck on the ACTION_UP
8844 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008845 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008846
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008847 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008848 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008849 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8850 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008851
8852 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8853 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008854 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008855 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008856 spy->assertNoEvents();
8857}
8858
8859TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008860 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008861
Prabir Pradhanfb549072023-10-05 19:17:36 +00008862 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008863
8864 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008865 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008866 WINDOW_LOCATION));
8867
8868 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8869 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
8870 ASSERT_TRUE(consumeSeq);
8871
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008872 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
8873 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008874
8875 monitor.finishEvent(*consumeSeq);
8876 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
8877
8878 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008879 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008880}
8881
8882// If a window is unresponsive, then you get anr. if the window later catches up and starts to
8883// process events, you don't get an anr. When the window later becomes unresponsive again, you
8884// get an ANR again.
8885// 1. tap -> block on ACTION_UP -> receive ANR
8886// 2. consume all pending events (= queue becomes healthy again)
8887// 3. tap again -> block on ACTION_UP again -> receive ANR second time
8888TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
8889 tapOnWindow();
8890
8891 mWindow->consumeMotionDown();
8892 // Block on 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 mWindow->consumeMotionUp(); // Now the connection should be healthy again
8896 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008897 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008898 mWindow->assertNoEvents();
8899
8900 tapOnWindow();
8901 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008902 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008903 mWindow->consumeMotionUp();
8904
8905 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008906 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008907 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008908 mWindow->assertNoEvents();
8909}
8910
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008911// If a connection remains unresponsive for a while, make sure policy is only notified once about
8912// it.
8913TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008914 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008915 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008916 WINDOW_LOCATION));
8917
8918 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008919 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008920 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008921 // 'notifyConnectionUnresponsive' should only be called once per connection
8922 mFakePolicy->assertNotifyAnrWasNotCalled();
8923 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008924 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008925 mWindow->consumeMotionEvent(
8926 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008927 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008928 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008929 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008930 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008931}
8932
8933/**
8934 * 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 -07008935 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008936 */
8937TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008938 // The timeouts in this test are established by relying on the fact that the "key waiting for
8939 // events timeout" is equal to 500ms.
8940 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008941 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008942 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008943
8944 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008945 const auto& [downSequenceNum, downEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008946 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008947 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008948 ASSERT_TRUE(upSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008949
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008950 // Don't finish the events yet, and send a key
8951 mDispatcher->notifyKey(
8952 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
8953 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8954 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008955 // Key will not be sent to the window, yet, because the window is still processing events
8956 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008957 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008958 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008959
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008960 std::this_thread::sleep_for(400ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008961 // if we wait long enough though, dispatcher will give up, and still send the key
8962 // to the focused window, even though we have not yet finished the motion event
8963 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8964 mWindow->finishEvent(*downSequenceNum);
8965 mWindow->finishEvent(*upSequenceNum);
8966}
8967
8968/**
8969 * If a window is processing a motion event, and then a key event comes in, the key event should
8970 * not go to the focused window until the motion is processed.
8971 * If then a new motion comes in, then the pending key event should be going to the currently
8972 * focused window right away.
8973 */
8974TEST_F(InputDispatcherSingleWindowAnr,
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008975 PendingKey_IsDeliveredWhileMotionIsProcessingAndNewTouchComesIn) {
8976 // The timeouts in this test are established by relying on the fact that the "key waiting for
8977 // events timeout" is equal to 500ms.
8978 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008979 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008980 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008981
8982 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008983 const auto& [downSequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008984 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008985 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008986 ASSERT_TRUE(upSequenceNum);
8987 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008988 mDispatcher->notifyKey(
8989 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
8990 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8991 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008992 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008993 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008994
8995 // Now tap down again. It should cause the pending key to go to the focused window right away.
8996 tapOnWindow();
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008997 // Now that we tapped, we should receive the key immediately.
8998 // Since there's still room for slowness, we use 200ms, which is much less than
8999 // the "key waiting for events' timeout of 500ms minus the already waited 100ms duration.
9000 std::unique_ptr<InputEvent> keyEvent = mWindow->consume(200ms);
9001 ASSERT_NE(nullptr, keyEvent);
9002 ASSERT_EQ(InputEventType::KEY, keyEvent->getType());
9003 ASSERT_THAT(static_cast<KeyEvent&>(*keyEvent), WithKeyAction(AKEY_EVENT_ACTION_DOWN));
9004 // it doesn't matter that we haven't ack'd the other events yet. We can finish events in any
9005 // order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009006 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
9007 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08009008 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9009 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009010 mWindow->assertNoEvents();
9011}
9012
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07009013/**
9014 * Send an event to the app and have the app not respond right away.
9015 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
9016 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
9017 * At some point, the window becomes responsive again.
9018 * Ensure that subsequent events get dropped, and the next gesture is delivered.
9019 */
9020TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
9021 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9022 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
9023 .build());
9024
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009025 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07009026 ASSERT_TRUE(sequenceNum);
9027 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9028 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
9029
9030 mWindow->finishEvent(*sequenceNum);
9031 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
9032 ASSERT_TRUE(mDispatcher->waitForIdle());
9033 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
9034
9035 // Now that the window is responsive, let's continue the gesture.
9036 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9037 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9038 .build());
9039
9040 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9041 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9042 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
9043 .build());
9044
9045 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9046 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9047 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
9048 .build());
9049 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9050 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9051 .build());
9052 // We already canceled this pointer, so the window shouldn't get any new events.
9053 mWindow->assertNoEvents();
9054
9055 // Start another one.
9056 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9057 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
9058 .build());
9059 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9060}
9061
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009062class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
9063 virtual void SetUp() override {
9064 InputDispatcherTest::SetUp();
9065
Chris Yea209fde2020-07-22 13:54:51 -07009066 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009067 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009068 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
9069 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009070 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009071 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009072 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009073
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009074 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
9075 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009076 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009077 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009078
9079 // Set focused application.
9080 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07009081 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009082
9083 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009084 mDispatcher->onWindowInfosChanged(
9085 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009086 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009087 mFocusedWindow->consumeFocusEvent(true);
9088 }
9089
9090 virtual void TearDown() override {
9091 InputDispatcherTest::TearDown();
9092
9093 mUnfocusedWindow.clear();
9094 mFocusedWindow.clear();
9095 }
9096
9097protected:
Chris Yea209fde2020-07-22 13:54:51 -07009098 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009099 sp<FakeWindowHandle> mUnfocusedWindow;
9100 sp<FakeWindowHandle> mFocusedWindow;
9101 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
9102 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
9103 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
9104
9105 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
9106
9107 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
9108
9109private:
9110 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009111 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009112 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009113 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009114 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009115 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009116 location));
9117 }
9118};
9119
9120// If we have 2 windows that are both unresponsive, the one with the shortest timeout
9121// should be ANR'd first.
9122TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009123 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009124 injectMotionEvent(*mDispatcher,
9125 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9126 AINPUT_SOURCE_TOUCHSCREEN)
9127 .pointer(PointerBuilder(0, ToolType::FINGER)
9128 .x(FOCUSED_WINDOW_LOCATION.x)
9129 .y(FOCUSED_WINDOW_LOCATION.y))
9130 .build()));
9131 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9132 injectMotionEvent(*mDispatcher,
9133 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
9134 AINPUT_SOURCE_TOUCHSCREEN)
9135 .pointer(PointerBuilder(0, ToolType::FINGER)
9136 .x(FOCUSED_WINDOW_LOCATION.x)
9137 .y(FOCUSED_WINDOW_LOCATION.y))
9138 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009139 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009140 mFocusedWindow->consumeMotionUp();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009141 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009142 // We consumed all events, so no ANR
9143 ASSERT_TRUE(mDispatcher->waitForIdle());
9144 mFakePolicy->assertNotifyAnrWasNotCalled();
9145
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009146 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009147 injectMotionEvent(*mDispatcher,
9148 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9149 AINPUT_SOURCE_TOUCHSCREEN)
9150 .pointer(PointerBuilder(0, ToolType::FINGER)
9151 .x(FOCUSED_WINDOW_LOCATION.x)
9152 .y(FOCUSED_WINDOW_LOCATION.y))
9153 .build()));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009154 const auto [unfocusedSequenceNum, _] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009155 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009156
9157 const std::chrono::duration timeout =
9158 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009159 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009160
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009161 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009162 mFocusedWindow->consumeMotionDown();
9163 // This cancel is generated because the connection was unresponsive
9164 mFocusedWindow->consumeMotionCancel();
9165 mFocusedWindow->assertNoEvents();
9166 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009167 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009168 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9169 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009170 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009171}
9172
9173// If we have 2 windows with identical timeouts that are both unresponsive,
9174// it doesn't matter which order they should have ANR.
9175// But we should receive ANR for both.
9176TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
9177 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009178 mUnfocusedWindow->setDispatchingTimeout(
9179 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009180 mDispatcher->onWindowInfosChanged(
9181 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009182
9183 tapOnFocusedWindow();
9184 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009185 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009186 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
9187 mFocusedWindow->getDispatchingTimeout(
9188 DISPATCHING_TIMEOUT)),
9189 mFakePolicy->getUnresponsiveWindowToken(0ms)};
9190
9191 ASSERT_THAT(anrConnectionTokens,
9192 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
9193 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009194
9195 ASSERT_TRUE(mDispatcher->waitForIdle());
9196 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009197
9198 mFocusedWindow->consumeMotionDown();
9199 mFocusedWindow->consumeMotionUp();
9200 mUnfocusedWindow->consumeMotionOutside();
9201
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009202 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
9203 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009204
9205 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009206 ASSERT_THAT(responsiveTokens,
9207 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
9208 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009209 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009210}
9211
9212// If a window is already not responding, the second tap on the same window should be ignored.
9213// We should also log an error to account for the dropped event (not tested here).
9214// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
9215TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
9216 tapOnFocusedWindow();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009217 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009218 // Receive the events, but don't respond
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009219 const auto [downEventSequenceNum, downEvent] = mFocusedWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009220 ASSERT_TRUE(downEventSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009221 const auto [upEventSequenceNum, upEvent] = mFocusedWindow->receiveEvent(); // ACTION_UP
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009222 ASSERT_TRUE(upEventSequenceNum);
9223 const std::chrono::duration timeout =
9224 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009225 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009226
9227 // Tap once again
9228 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009229 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009230 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009231 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009232 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009233 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009234 FOCUSED_WINDOW_LOCATION));
9235 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
9236 // valid touch target
9237 mUnfocusedWindow->assertNoEvents();
9238
9239 // Consume the first tap
9240 mFocusedWindow->finishEvent(*downEventSequenceNum);
9241 mFocusedWindow->finishEvent(*upEventSequenceNum);
9242 ASSERT_TRUE(mDispatcher->waitForIdle());
9243 // The second tap did not go to the focused window
9244 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009245 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08009246 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9247 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009248 mFakePolicy->assertNotifyAnrWasNotCalled();
9249}
9250
9251// If you tap outside of all windows, there will not be ANR
9252TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009253 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009254 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009255 LOCATION_OUTSIDE_ALL_WINDOWS));
9256 ASSERT_TRUE(mDispatcher->waitForIdle());
9257 mFakePolicy->assertNotifyAnrWasNotCalled();
9258}
9259
9260// Since the focused window is paused, tapping on it should not produce any events
9261TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
9262 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009263 mDispatcher->onWindowInfosChanged(
9264 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009265
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009266 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009267 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009268 FOCUSED_WINDOW_LOCATION));
9269
9270 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
9271 ASSERT_TRUE(mDispatcher->waitForIdle());
9272 // Should not ANR because the window is paused, and touches shouldn't go to it
9273 mFakePolicy->assertNotifyAnrWasNotCalled();
9274
9275 mFocusedWindow->assertNoEvents();
9276 mUnfocusedWindow->assertNoEvents();
9277}
9278
9279/**
9280 * 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 -07009281 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009282 * If a different window becomes focused at this time, the key should go to that window instead.
9283 *
9284 * Warning!!!
9285 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
9286 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009287 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009288 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
9289 *
9290 * If that value changes, this test should also change.
9291 */
9292TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
9293 // Set a long ANR timeout to prevent it from triggering
9294 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009295 mDispatcher->onWindowInfosChanged(
9296 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009297
9298 tapOnUnfocusedWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009299 const auto [downSequenceNum, downEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009300 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009301 const auto [upSequenceNum, upEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009302 ASSERT_TRUE(upSequenceNum);
9303 // Don't finish the events yet, and send a key
9304 // Injection will succeed because we will eventually give up and send the key to the focused
9305 // window even if motions are still being processed.
9306
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009307 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009308 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9309 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009310 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009311 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009312 // and the key remains pending, waiting for the touch events to be processed.
9313 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
9314 // under the hood.
9315 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
9316 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009317
9318 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07009319 mFocusedWindow->setFocusable(false);
9320 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009321 mDispatcher->onWindowInfosChanged(
9322 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009323 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009324
9325 // Focus events should precede the key events
9326 mUnfocusedWindow->consumeFocusEvent(true);
9327 mFocusedWindow->consumeFocusEvent(false);
9328
9329 // Finish the tap events, which should unblock dispatcher
9330 mUnfocusedWindow->finishEvent(*downSequenceNum);
9331 mUnfocusedWindow->finishEvent(*upSequenceNum);
9332
9333 // Now that all queues are cleared and no backlog in the connections, the key event
9334 // can finally go to the newly focused "mUnfocusedWindow".
9335 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9336 mFocusedWindow->assertNoEvents();
9337 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009338 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009339}
9340
9341// When the touch stream is split across 2 windows, and one of them does not respond,
9342// then ANR should be raised and the touch should be canceled for the unresponsive window.
9343// The other window should not be affected by that.
9344TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
9345 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00009346 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9347 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9348 {FOCUSED_WINDOW_LOCATION}));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009349 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009350
9351 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00009352 mDispatcher->notifyMotion(
9353 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9354 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009355
9356 const std::chrono::duration timeout =
9357 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009358 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009359
9360 mUnfocusedWindow->consumeMotionDown();
9361 mFocusedWindow->consumeMotionDown();
9362 // Focused window may or may not receive ACTION_MOVE
9363 // But it should definitely receive ACTION_CANCEL due to the ANR
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009364 const auto [moveOrCancelSequenceNum, event] = mFocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009365 ASSERT_TRUE(moveOrCancelSequenceNum);
9366 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
9367 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009368 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009369 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
9370 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
9371 mFocusedWindow->consumeMotionCancel();
9372 } else {
9373 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
9374 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009375 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009376 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9377 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009378
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009379 mUnfocusedWindow->assertNoEvents();
9380 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009381 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009382}
9383
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009384/**
9385 * If we have no focused window, and a key comes in, we start the ANR timer.
9386 * The focused application should add a focused window before the timer runs out to prevent ANR.
9387 *
9388 * If the user touches another application during this time, the key should be dropped.
9389 * Next, if a new focused window comes in, without toggling the focused application,
9390 * then no ANR should occur.
9391 *
9392 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
9393 * but in some cases the policy may not update the focused application.
9394 */
9395TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
9396 std::shared_ptr<FakeApplicationHandle> focusedApplication =
9397 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07009398 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009399 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
9400 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
9401 mFocusedWindow->setFocusable(false);
9402
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009403 mDispatcher->onWindowInfosChanged(
9404 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009405 mFocusedWindow->consumeFocusEvent(false);
9406
9407 // Send a key. The ANR timer should start because there is no focused window.
9408 // 'focusedApplication' will get blamed if this timer completes.
9409 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009410 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009411 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9412 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00009413 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009414 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009415
9416 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
9417 // then the injected touches won't cause the focused event to get dropped.
9418 // The dispatcher only checks for whether the queue should be pruned upon queueing.
9419 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
9420 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
9421 // For this test, it means that the key would get delivered to the window once it becomes
9422 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009423 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009424
9425 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00009426 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9427 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9428 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009429
9430 // We do not consume the motion right away, because that would require dispatcher to first
9431 // process (== drop) the key event, and by that time, ANR will be raised.
9432 // Set the focused window first.
9433 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009434 mDispatcher->onWindowInfosChanged(
9435 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009436 setFocusedWindow(mFocusedWindow);
9437 mFocusedWindow->consumeFocusEvent(true);
9438 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
9439 // to another application. This could be a bug / behaviour in the policy.
9440
9441 mUnfocusedWindow->consumeMotionDown();
9442
9443 ASSERT_TRUE(mDispatcher->waitForIdle());
9444 // Should not ANR because we actually have a focused window. It was just added too slowly.
9445 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
9446}
9447
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -08009448/**
9449 * If we are pruning input queue, we should never drop pointer events. Otherwise, we risk having
9450 * an inconsistent event stream inside the dispatcher. In this test, we make sure that the
9451 * dispatcher doesn't prune pointer events incorrectly.
9452 *
9453 * This test reproduces a crash in InputDispatcher.
9454 * To reproduce the crash, we need to simulate the conditions for "pruning input queue" to occur.
9455 *
9456 * Keep the currently focused application (mApplication), and have no focused window.
9457 * We set up two additional windows:
9458 * 1) The navigation bar window. This simulates the system "NavigationBar", which is used in the
9459 * 3-button navigation mode. This window injects a BACK button when it's touched. 2) The application
9460 * window. This window is not focusable, but is touchable.
9461 *
9462 * We first touch the navigation bar, which causes it to inject a key. Since there's no focused
9463 * window, the dispatcher doesn't process this key, and all other events inside dispatcher are now
9464 * blocked. The dispatcher is waiting for 'mApplication' to add a focused window.
9465 *
9466 * Now, we touch "Another window". This window is owned by a different application than
9467 * 'mApplication'. This causes the dispatcher to stop waiting for 'mApplication' to add a focused
9468 * window. Now, the "pruning input queue" behaviour should kick in, and the dispatcher should start
9469 * dropping the events from its queue. Ensure that no crash occurs.
9470 *
9471 * In this test, we are setting long timeouts to prevent ANRs and events dropped due to being stale.
9472 * This does not affect the test running time.
9473 */
9474TEST_F(InputDispatcherMultiWindowAnr, PruningInputQueueShouldNotDropPointerEvents) {
9475 std::shared_ptr<FakeApplicationHandle> systemUiApplication =
9476 std::make_shared<FakeApplicationHandle>();
9477 systemUiApplication->setDispatchingTimeout(3000ms);
9478 mFakePolicy->setStaleEventTimeout(3000ms);
9479 sp<FakeWindowHandle> navigationBar =
9480 sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
9481 ADISPLAY_ID_DEFAULT);
9482 navigationBar->setFocusable(false);
9483 navigationBar->setWatchOutsideTouch(true);
9484 navigationBar->setFrame(Rect(0, 0, 100, 100));
9485
9486 mApplication->setDispatchingTimeout(3000ms);
9487 // 'mApplication' is already focused, but we call it again here to make it explicit.
9488 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
9489
9490 std::shared_ptr<FakeApplicationHandle> anotherApplication =
9491 std::make_shared<FakeApplicationHandle>();
9492 sp<FakeWindowHandle> appWindow =
9493 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
9494 ADISPLAY_ID_DEFAULT);
9495 appWindow->setFocusable(false);
9496 appWindow->setFrame(Rect(100, 100, 200, 200));
9497
9498 mDispatcher->onWindowInfosChanged(
9499 {{*navigationBar->getInfo(), *appWindow->getInfo()}, {}, 0, 0});
9500 // 'mFocusedWindow' is no longer in the dispatcher window list, and therefore loses focus
9501 mFocusedWindow->consumeFocusEvent(false);
9502
9503 // Touch down the navigation bar. It consumes the touch and injects a key into the dispatcher
9504 // in response.
9505 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9506 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9507 .build());
9508 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9509
9510 // Key will not be sent anywhere because we have no focused window. It will remain pending.
9511 // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
9512 InputEventInjectionResult result =
9513 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9514 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
9515 /*allowKeyRepeat=*/false);
9516 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
9517
9518 // Finish the gesture - lift up finger and inject ACTION_UP key event
9519 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9520 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9521 .build());
9522 result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9523 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
9524 /*allowKeyRepeat=*/false);
9525 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
9526 // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
9527 // getting any events yet.
9528 navigationBar->assertNoEvents();
9529
9530 // Now touch "Another window". This touch is going to a different application than the one we
9531 // are waiting for (which is 'mApplication').
9532 // This should cause the dispatcher to drop the pending focus-dispatched events (like the key
9533 // trying to be injected) and to continue processing the rest of the events in the original
9534 // order.
9535 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9536 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
9537 .build());
9538 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_UP));
9539 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
9540 appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9541
9542 appWindow->assertNoEvents();
9543 navigationBar->assertNoEvents();
9544}
9545
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009546// These tests ensure we cannot send touch events to a window that's positioned behind a window
9547// that has feature NO_INPUT_CHANNEL.
9548// Layout:
9549// Top (closest to user)
9550// mNoInputWindow (above all windows)
9551// mBottomWindow
9552// Bottom (furthest from user)
9553class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
9554 virtual void SetUp() override {
9555 InputDispatcherTest::SetUp();
9556
9557 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009558 mNoInputWindow =
9559 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
9560 "Window without input channel", ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009561 /*createInputChannel=*/false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009562 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009563 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
9564 // It's perfectly valid for this window to not have an associated input channel
9565
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009566 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
9567 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009568 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
9569
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009570 mDispatcher->onWindowInfosChanged(
9571 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009572 }
9573
9574protected:
9575 std::shared_ptr<FakeApplicationHandle> mApplication;
9576 sp<FakeWindowHandle> mNoInputWindow;
9577 sp<FakeWindowHandle> mBottomWindow;
9578};
9579
9580TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
9581 PointF touchedPoint = {10, 10};
9582
Prabir Pradhan678438e2023-04-13 19:32:51 +00009583 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9584 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9585 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009586
9587 mNoInputWindow->assertNoEvents();
9588 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
9589 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
9590 // and therefore should prevent mBottomWindow from receiving touches
9591 mBottomWindow->assertNoEvents();
9592}
9593
9594/**
9595 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
9596 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
9597 */
9598TEST_F(InputDispatcherMultiWindowOcclusionTests,
9599 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009600 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
9601 "Window with input channel and NO_INPUT_CHANNEL",
9602 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009603
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009604 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009605 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009606 mDispatcher->onWindowInfosChanged(
9607 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009608
9609 PointF touchedPoint = {10, 10};
9610
Prabir Pradhan678438e2023-04-13 19:32:51 +00009611 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9612 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9613 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009614
9615 mNoInputWindow->assertNoEvents();
9616 mBottomWindow->assertNoEvents();
9617}
9618
Vishnu Nair958da932020-08-21 17:12:37 -07009619class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
9620protected:
9621 std::shared_ptr<FakeApplicationHandle> mApp;
9622 sp<FakeWindowHandle> mWindow;
9623 sp<FakeWindowHandle> mMirror;
9624
9625 virtual void SetUp() override {
9626 InputDispatcherTest::SetUp();
9627 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009628 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009629 mMirror = mWindow->clone(ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07009630 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
9631 mWindow->setFocusable(true);
9632 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009633 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009634 }
9635};
9636
9637TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
9638 // Request focus on a mirrored window
9639 setFocusedWindow(mMirror);
9640
9641 // window gets focused
9642 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009643 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009644 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009645 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
9646}
9647
9648// A focused & mirrored window remains focused only if the window and its mirror are both
9649// focusable.
9650TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
9651 setFocusedWindow(mMirror);
9652
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009653 // window gets focused because it is above the mirror
Vishnu Nair958da932020-08-21 17:12:37 -07009654 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009655 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009656 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009657 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009658 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009659 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009660 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9661
9662 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009663 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009664
9665 // window loses focus since one of the windows associated with the token in not focusable
9666 mWindow->consumeFocusEvent(false);
9667
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009668 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009669 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009670 mWindow->assertNoEvents();
9671}
9672
9673// A focused & mirrored window remains focused until the window and its mirror both become
9674// invisible.
9675TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
9676 setFocusedWindow(mMirror);
9677
9678 // window gets focused
9679 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009680 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009681 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009682 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009683 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009684 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009685 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9686
9687 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009688 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009689
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009690 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009691 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009692 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009693 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009694 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009695 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9696
9697 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009698 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009699
9700 // window loses focus only after all windows associated with the token become invisible.
9701 mWindow->consumeFocusEvent(false);
9702
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009703 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009704 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009705 mWindow->assertNoEvents();
9706}
9707
9708// A focused & mirrored window remains focused until both windows are removed.
9709TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
9710 setFocusedWindow(mMirror);
9711
9712 // window gets focused
9713 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009714 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009715 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009716 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009717 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009718 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009719 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9720
9721 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009722 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009723
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009724 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009725 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009726 mMirror->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009727 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009728 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009729 mMirror->consumeKeyUp(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07009730
9731 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009732 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009733 mWindow->consumeFocusEvent(false);
9734
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009735 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009736 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009737 mWindow->assertNoEvents();
9738}
9739
9740// Focus request can be pending until one window becomes visible.
9741TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
9742 // Request focus on an invisible mirror.
9743 mWindow->setVisible(false);
9744 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009745 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009746 setFocusedWindow(mMirror);
9747
9748 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009749 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009750 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9751 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07009752
9753 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009754 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009755
9756 // window gets focused
9757 mWindow->consumeFocusEvent(true);
9758 // window gets the pending key event
9759 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9760}
Prabir Pradhan99987712020-11-10 18:43:05 -08009761
9762class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
9763protected:
9764 std::shared_ptr<FakeApplicationHandle> mApp;
9765 sp<FakeWindowHandle> mWindow;
9766 sp<FakeWindowHandle> mSecondWindow;
9767
9768 void SetUp() override {
9769 InputDispatcherTest::SetUp();
9770 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009771 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009772 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009773 mSecondWindow =
9774 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009775 mSecondWindow->setFocusable(true);
9776
9777 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009778 mDispatcher->onWindowInfosChanged(
9779 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08009780
9781 setFocusedWindow(mWindow);
9782 mWindow->consumeFocusEvent(true);
9783 }
9784
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009785 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009786 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08009787 }
9788
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009789 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
9790 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08009791 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009792 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
9793 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009794 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009795 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08009796 }
9797};
9798
9799TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
9800 // Ensure that capture cannot be obtained for unfocused windows.
9801 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
9802 mFakePolicy->assertSetPointerCaptureNotCalled();
9803 mSecondWindow->assertNoEvents();
9804
9805 // Ensure that capture can be enabled from the focus window.
9806 requestAndVerifyPointerCapture(mWindow, true);
9807
9808 // Ensure that capture cannot be disabled from a window that does not have capture.
9809 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
9810 mFakePolicy->assertSetPointerCaptureNotCalled();
9811
9812 // Ensure that capture can be disabled from the window with capture.
9813 requestAndVerifyPointerCapture(mWindow, false);
9814}
9815
9816TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009817 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009818
9819 setFocusedWindow(mSecondWindow);
9820
9821 // Ensure that the capture disabled event was sent first.
9822 mWindow->consumeCaptureEvent(false);
9823 mWindow->consumeFocusEvent(false);
9824 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009825 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009826
9827 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009828 notifyPointerCaptureChanged({});
9829 notifyPointerCaptureChanged(request);
9830 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08009831 mWindow->assertNoEvents();
9832 mSecondWindow->assertNoEvents();
9833 mFakePolicy->assertSetPointerCaptureNotCalled();
9834}
9835
9836TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009837 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009838
9839 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009840 notifyPointerCaptureChanged({});
9841 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009842
9843 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009844 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009845 mWindow->consumeCaptureEvent(false);
9846 mWindow->assertNoEvents();
9847}
9848
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009849TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
9850 requestAndVerifyPointerCapture(mWindow, true);
9851
9852 // The first window loses focus.
9853 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009854 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009855 mWindow->consumeCaptureEvent(false);
9856
9857 // Request Pointer Capture from the second window before the notification from InputReader
9858 // arrives.
9859 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009860 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009861
9862 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009863 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009864
9865 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009866 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009867
9868 mSecondWindow->consumeFocusEvent(true);
9869 mSecondWindow->consumeCaptureEvent(true);
9870}
9871
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009872TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
9873 // App repeatedly enables and disables capture.
9874 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9875 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9876 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9877 mFakePolicy->assertSetPointerCaptureCalled(false);
9878 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9879 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9880
9881 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
9882 // first request is now stale, this should do nothing.
9883 notifyPointerCaptureChanged(firstRequest);
9884 mWindow->assertNoEvents();
9885
9886 // InputReader notifies that the second request was enabled.
9887 notifyPointerCaptureChanged(secondRequest);
9888 mWindow->consumeCaptureEvent(true);
9889}
9890
Prabir Pradhan7092e262022-05-03 16:51:09 +00009891TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
9892 requestAndVerifyPointerCapture(mWindow, true);
9893
9894 // App toggles pointer capture off and on.
9895 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9896 mFakePolicy->assertSetPointerCaptureCalled(false);
9897
9898 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9899 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9900
9901 // InputReader notifies that the latest "enable" request was processed, while skipping over the
9902 // preceding "disable" request.
9903 notifyPointerCaptureChanged(enableRequest);
9904
9905 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
9906 // any notifications.
9907 mWindow->assertNoEvents();
9908}
9909
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009910/**
9911 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
9912 * mouse movements don't affect the previous mouse hovering state.
9913 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
9914 * HOVER_MOVE events).
9915 */
9916TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
9917 // Mouse hover on the window
9918 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
9919 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9920 .build());
9921 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9922 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9923 .build());
9924
9925 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
9926 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
9927
9928 // Start pointer capture
9929 requestAndVerifyPointerCapture(mWindow, true);
9930
9931 // Send some relative mouse movements and receive them in the window.
9932 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
9933 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
9934 .build());
9935 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
9936 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
9937
9938 // Stop pointer capture
9939 requestAndVerifyPointerCapture(mWindow, false);
9940
9941 // Continue hovering on the window
9942 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9943 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
9944 .build());
9945 mWindow->consumeMotionEvent(
9946 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
9947
9948 mWindow->assertNoEvents();
9949}
9950
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009951class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
9952protected:
9953 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00009954
9955 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
9956 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
9957
9958 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
9959 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9960
9961 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
9962 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
9963 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9964 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
9965 MAXIMUM_OBSCURING_OPACITY);
9966
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009967 static constexpr gui::Uid TOUCHED_APP_UID{10001};
9968 static constexpr gui::Uid APP_B_UID{10002};
9969 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009970
9971 sp<FakeWindowHandle> mTouchWindow;
9972
9973 virtual void SetUp() override {
9974 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009975 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009976 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
9977 }
9978
9979 virtual void TearDown() override {
9980 InputDispatcherTest::TearDown();
9981 mTouchWindow.clear();
9982 }
9983
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009984 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05009985 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009986 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009987 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009988 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009989 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009990 return window;
9991 }
9992
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009993 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009994 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
9995 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009996 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009997 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009998 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009999 return window;
10000 }
10001
10002 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010003 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10004 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10005 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010006 }
10007};
10008
10009TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010010 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010011 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010012 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010013
10014 touch();
10015
10016 mTouchWindow->assertNoEvents();
10017}
10018
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010019TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +000010020 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
10021 const sp<FakeWindowHandle>& w =
10022 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010023 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010024
10025 touch();
10026
10027 mTouchWindow->assertNoEvents();
10028}
10029
10030TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010031 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
10032 const sp<FakeWindowHandle>& w =
10033 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010034 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010035
10036 touch();
10037
10038 w->assertNoEvents();
10039}
10040
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010041TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010042 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010043 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010044
10045 touch();
10046
10047 mTouchWindow->consumeAnyMotionDown();
10048}
10049
10050TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010051 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010052 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010053 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010054 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010055
10056 touch({PointF{100, 100}});
10057
10058 mTouchWindow->consumeAnyMotionDown();
10059}
10060
10061TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010062 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010063 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010064 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010065
10066 touch();
10067
10068 mTouchWindow->consumeAnyMotionDown();
10069}
10070
10071TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
10072 const sp<FakeWindowHandle>& w =
10073 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010074 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010075
10076 touch();
10077
10078 mTouchWindow->consumeAnyMotionDown();
10079}
10080
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010081TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
10082 const sp<FakeWindowHandle>& w =
10083 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010084 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010085
10086 touch();
10087
10088 w->assertNoEvents();
10089}
10090
10091/**
10092 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
10093 * inside) while letting them pass-through. Note that even though touch passes through the occluding
10094 * window, the occluding window will still receive ACTION_OUTSIDE event.
10095 */
10096TEST_F(InputDispatcherUntrustedTouchesTest,
10097 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
10098 const sp<FakeWindowHandle>& w =
10099 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010100 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010101 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010102
10103 touch();
10104
10105 w->consumeMotionOutside();
10106}
10107
10108TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
10109 const sp<FakeWindowHandle>& w =
10110 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010111 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010112 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010113
10114 touch();
10115
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010116 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010117}
10118
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010119TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010120 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010121 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10122 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010123 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010124
10125 touch();
10126
10127 mTouchWindow->consumeAnyMotionDown();
10128}
10129
10130TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
10131 const sp<FakeWindowHandle>& w =
10132 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10133 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010134 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010135
10136 touch();
10137
10138 mTouchWindow->consumeAnyMotionDown();
10139}
10140
10141TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010142 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010143 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10144 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010145 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010146
10147 touch();
10148
10149 mTouchWindow->assertNoEvents();
10150}
10151
10152TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
10153 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
10154 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010155 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
10156 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010157 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010158 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
10159 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010160 mDispatcher->onWindowInfosChanged(
10161 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010162
10163 touch();
10164
10165 mTouchWindow->assertNoEvents();
10166}
10167
10168TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
10169 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
10170 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010171 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
10172 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010173 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010174 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
10175 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010176 mDispatcher->onWindowInfosChanged(
10177 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010178
10179 touch();
10180
10181 mTouchWindow->consumeAnyMotionDown();
10182}
10183
10184TEST_F(InputDispatcherUntrustedTouchesTest,
10185 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
10186 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010187 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10188 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010189 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010190 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10191 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010192 mDispatcher->onWindowInfosChanged(
10193 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010194
10195 touch();
10196
10197 mTouchWindow->consumeAnyMotionDown();
10198}
10199
10200TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
10201 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010202 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10203 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010204 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010205 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10206 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010207 mDispatcher->onWindowInfosChanged(
10208 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010209
10210 touch();
10211
10212 mTouchWindow->assertNoEvents();
10213}
10214
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010215TEST_F(InputDispatcherUntrustedTouchesTest,
10216 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
10217 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010218 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10219 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010220 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010221 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10222 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010223 mDispatcher->onWindowInfosChanged(
10224 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010225
10226 touch();
10227
10228 mTouchWindow->assertNoEvents();
10229}
10230
10231TEST_F(InputDispatcherUntrustedTouchesTest,
10232 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
10233 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010234 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10235 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010236 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010237 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10238 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010239 mDispatcher->onWindowInfosChanged(
10240 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010241
10242 touch();
10243
10244 mTouchWindow->consumeAnyMotionDown();
10245}
10246
10247TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
10248 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010249 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10250 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010251 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010252
10253 touch();
10254
10255 mTouchWindow->consumeAnyMotionDown();
10256}
10257
10258TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
10259 const sp<FakeWindowHandle>& w =
10260 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010261 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010262
10263 touch();
10264
10265 mTouchWindow->consumeAnyMotionDown();
10266}
10267
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010268TEST_F(InputDispatcherUntrustedTouchesTest,
10269 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
10270 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
10271 const sp<FakeWindowHandle>& w =
10272 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010273 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010274
10275 touch();
10276
10277 mTouchWindow->assertNoEvents();
10278}
10279
10280TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
10281 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
10282 const sp<FakeWindowHandle>& w =
10283 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010284 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010285
10286 touch();
10287
10288 mTouchWindow->consumeAnyMotionDown();
10289}
10290
10291TEST_F(InputDispatcherUntrustedTouchesTest,
10292 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
10293 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
10294 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010295 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10296 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010297 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010298
10299 touch();
10300
10301 mTouchWindow->consumeAnyMotionDown();
10302}
10303
10304TEST_F(InputDispatcherUntrustedTouchesTest,
10305 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
10306 const sp<FakeWindowHandle>& w1 =
10307 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
10308 OPACITY_BELOW_THRESHOLD);
10309 const sp<FakeWindowHandle>& w2 =
10310 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10311 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010312 mDispatcher->onWindowInfosChanged(
10313 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010314
10315 touch();
10316
10317 mTouchWindow->assertNoEvents();
10318}
10319
10320/**
10321 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
10322 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
10323 * (which alone would result in allowing touches) does not affect the blocking behavior.
10324 */
10325TEST_F(InputDispatcherUntrustedTouchesTest,
10326 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
10327 const sp<FakeWindowHandle>& wB =
10328 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
10329 OPACITY_BELOW_THRESHOLD);
10330 const sp<FakeWindowHandle>& wC =
10331 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10332 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010333 mDispatcher->onWindowInfosChanged(
10334 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010335
10336 touch();
10337
10338 mTouchWindow->assertNoEvents();
10339}
10340
10341/**
10342 * This test is testing that a window from a different UID but with same application token doesn't
10343 * block the touch. Apps can share the application token for close UI collaboration for example.
10344 */
10345TEST_F(InputDispatcherUntrustedTouchesTest,
10346 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
10347 const sp<FakeWindowHandle>& w =
10348 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
10349 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010350 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010351
10352 touch();
10353
10354 mTouchWindow->consumeAnyMotionDown();
10355}
10356
arthurhungb89ccb02020-12-30 16:19:01 +080010357class InputDispatcherDragTests : public InputDispatcherTest {
10358protected:
10359 std::shared_ptr<FakeApplicationHandle> mApp;
10360 sp<FakeWindowHandle> mWindow;
10361 sp<FakeWindowHandle> mSecondWindow;
10362 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010363 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010364 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
10365 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +080010366
10367 void SetUp() override {
10368 InputDispatcherTest::SetUp();
10369 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010370 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080010371 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080010372
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010373 mSecondWindow =
10374 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080010375 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080010376
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010377 mSpyWindow =
10378 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010379 mSpyWindow->setSpy(true);
10380 mSpyWindow->setTrustedOverlay(true);
10381 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
10382
arthurhungb89ccb02020-12-30 16:19:01 +080010383 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010384 mDispatcher->onWindowInfosChanged(
10385 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
10386 {},
10387 0,
10388 0});
arthurhungb89ccb02020-12-30 16:19:01 +080010389 }
10390
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010391 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
10392 switch (fromSource) {
10393 case AINPUT_SOURCE_TOUCHSCREEN:
10394 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010395 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010396 ADISPLAY_ID_DEFAULT, {50, 50}))
10397 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10398 break;
10399 case AINPUT_SOURCE_STYLUS:
10400 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010401 injectMotionEvent(*mDispatcher,
10402 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10403 AINPUT_SOURCE_STYLUS)
10404 .buttonState(
10405 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
10406 .pointer(PointerBuilder(0, ToolType::STYLUS)
10407 .x(50)
10408 .y(50))
10409 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010410 break;
10411 case AINPUT_SOURCE_MOUSE:
10412 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010413 injectMotionEvent(*mDispatcher,
10414 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10415 AINPUT_SOURCE_MOUSE)
10416 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
10417 .pointer(PointerBuilder(MOUSE_POINTER_ID,
10418 ToolType::MOUSE)
10419 .x(50)
10420 .y(50))
10421 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010422 break;
10423 default:
10424 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
10425 }
arthurhungb89ccb02020-12-30 16:19:01 +080010426
10427 // Window should receive motion event.
10428 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010429 // Spy window should also receive motion event
10430 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000010431 }
10432
10433 // Start performing drag, we will create a drag window and transfer touch to it.
10434 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
10435 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010436 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +000010437 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010438 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +000010439 }
arthurhungb89ccb02020-12-30 16:19:01 +080010440
10441 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010442 mDragWindow =
10443 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010444 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010445 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
10446 *mWindow->getInfo(), *mSecondWindow->getInfo()},
10447 {},
10448 0,
10449 0});
arthurhungb89ccb02020-12-30 16:19:01 +080010450
10451 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +000010452 bool transferred =
10453 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +000010454 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +000010455 if (transferred) {
10456 mWindow->consumeMotionCancel();
10457 mDragWindow->consumeMotionDown();
10458 }
10459 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +080010460 }
10461};
10462
10463TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010464 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +080010465
10466 // Move on window.
10467 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010468 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010469 ADISPLAY_ID_DEFAULT, {50, 50}))
10470 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10471 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10472 mWindow->consumeDragEvent(false, 50, 50);
10473 mSecondWindow->assertNoEvents();
10474
10475 // Move to another window.
10476 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010477 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010478 ADISPLAY_ID_DEFAULT, {150, 50}))
10479 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10480 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10481 mWindow->consumeDragEvent(true, 150, 50);
10482 mSecondWindow->consumeDragEvent(false, 50, 50);
10483
10484 // Move back to original window.
10485 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010486 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010487 ADISPLAY_ID_DEFAULT, {50, 50}))
10488 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10489 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10490 mWindow->consumeDragEvent(false, 50, 50);
10491 mSecondWindow->consumeDragEvent(true, -50, 50);
10492
10493 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010494 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10495 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080010496 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10497 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10498 mWindow->assertNoEvents();
10499 mSecondWindow->assertNoEvents();
10500}
10501
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010502TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010503 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010504
10505 // No cancel event after drag start
10506 mSpyWindow->assertNoEvents();
10507
10508 const MotionEvent secondFingerDownEvent =
10509 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10510 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010511 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10512 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010513 .build();
10514 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010515 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010516 InputEventInjectionSync::WAIT_FOR_RESULT))
10517 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10518
10519 // Receives cancel for first pointer after next pointer down
10520 mSpyWindow->consumeMotionCancel();
10521 mSpyWindow->consumeMotionDown();
10522
10523 mSpyWindow->assertNoEvents();
10524}
10525
arthurhungf452d0b2021-01-06 00:19:52 +080010526TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010527 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +080010528
10529 // Move on window.
10530 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010531 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +080010532 ADISPLAY_ID_DEFAULT, {50, 50}))
10533 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10534 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10535 mWindow->consumeDragEvent(false, 50, 50);
10536 mSecondWindow->assertNoEvents();
10537
10538 // Move to another window.
10539 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010540 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +080010541 ADISPLAY_ID_DEFAULT, {150, 50}))
10542 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10543 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10544 mWindow->consumeDragEvent(true, 150, 50);
10545 mSecondWindow->consumeDragEvent(false, 50, 50);
10546
10547 // drop to another window.
10548 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010549 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +080010550 {150, 50}))
10551 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10552 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010553 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +080010554 mWindow->assertNoEvents();
10555 mSecondWindow->assertNoEvents();
10556}
10557
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010558TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
10559 startDrag();
10560
10561 // No cancel event after drag start
10562 mSpyWindow->assertNoEvents();
10563
10564 const MotionEvent secondFingerDownEvent =
10565 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10566 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10567 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10568 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10569 .build();
10570 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10571 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10572 InputEventInjectionSync::WAIT_FOR_RESULT))
10573 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10574
10575 // Receives cancel for first pointer after next pointer down
10576 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080010577 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010578 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
10579
10580 mSpyWindow->assertNoEvents();
10581
10582 // Spy window calls pilfer pointers
10583 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
10584 mDragWindow->assertNoEvents();
10585
10586 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010587 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010588 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10589 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
10590 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10591 .build();
10592 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010593 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010594 InputEventInjectionSync::WAIT_FOR_RESULT))
10595 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10596
10597 // Drag window should still receive the new event
10598 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
10599 mDragWindow->assertNoEvents();
10600}
10601
arthurhung6d4bed92021-03-17 11:59:33 +080010602TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010603 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +080010604
10605 // Move on window and keep button pressed.
10606 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010607 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010608 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10609 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010610 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010611 .build()))
10612 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10613 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10614 mWindow->consumeDragEvent(false, 50, 50);
10615 mSecondWindow->assertNoEvents();
10616
10617 // Move to another window and release button, expect to drop item.
10618 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010619 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010620 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10621 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010622 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010623 .build()))
10624 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10625 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10626 mWindow->assertNoEvents();
10627 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010628 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +080010629
10630 // nothing to the window.
10631 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010632 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010633 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
10634 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010635 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010636 .build()))
10637 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10638 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10639 mWindow->assertNoEvents();
10640 mSecondWindow->assertNoEvents();
10641}
10642
Arthur Hung54745652022-04-20 07:17:41 +000010643TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010644 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +080010645
10646 // Set second window invisible.
10647 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010648 mDispatcher->onWindowInfosChanged(
10649 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +080010650
10651 // Move on window.
10652 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010653 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010654 ADISPLAY_ID_DEFAULT, {50, 50}))
10655 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10656 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10657 mWindow->consumeDragEvent(false, 50, 50);
10658 mSecondWindow->assertNoEvents();
10659
10660 // Move to another window.
10661 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010662 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010663 ADISPLAY_ID_DEFAULT, {150, 50}))
10664 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10665 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10666 mWindow->consumeDragEvent(true, 150, 50);
10667 mSecondWindow->assertNoEvents();
10668
10669 // drop to another window.
10670 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010671 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010672 {150, 50}))
10673 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10674 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010675 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010676 mWindow->assertNoEvents();
10677 mSecondWindow->assertNoEvents();
10678}
10679
Arthur Hung54745652022-04-20 07:17:41 +000010680TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010681 // Ensure window could track pointerIds if it didn't support split touch.
10682 mWindow->setPreventSplitting(true);
10683
Arthur Hung54745652022-04-20 07:17:41 +000010684 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010685 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010686 {50, 50}))
10687 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10688 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10689
10690 const MotionEvent secondFingerDownEvent =
10691 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10692 .displayId(ADISPLAY_ID_DEFAULT)
10693 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010694 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10695 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010696 .build();
10697 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010698 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010699 InputEventInjectionSync::WAIT_FOR_RESULT))
10700 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010701 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +000010702
10703 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010704 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010705}
10706
10707TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
10708 // First down on second window.
10709 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010710 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010711 {150, 50}))
10712 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10713
10714 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10715
10716 // Second down on first window.
10717 const MotionEvent secondFingerDownEvent =
10718 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10719 .displayId(ADISPLAY_ID_DEFAULT)
10720 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010721 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10722 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010723 .build();
10724 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010725 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010726 InputEventInjectionSync::WAIT_FOR_RESULT))
10727 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10728 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10729
10730 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010731 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010732
10733 // Move on window.
10734 const MotionEvent secondFingerMoveEvent =
10735 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10736 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010737 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10738 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010739 .build();
10740 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010741 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010742 InputEventInjectionSync::WAIT_FOR_RESULT));
10743 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10744 mWindow->consumeDragEvent(false, 50, 50);
10745 mSecondWindow->consumeMotionMove();
10746
10747 // Release the drag pointer should perform drop.
10748 const MotionEvent secondFingerUpEvent =
10749 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10750 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010751 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10752 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010753 .build();
10754 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010755 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010756 InputEventInjectionSync::WAIT_FOR_RESULT));
10757 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010758 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000010759 mWindow->assertNoEvents();
10760 mSecondWindow->consumeMotionMove();
10761}
10762
Arthur Hung3915c1f2022-05-31 07:17:17 +000010763TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010764 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000010765
10766 // Update window of second display.
10767 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010768 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010769 mDispatcher->onWindowInfosChanged(
10770 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10771 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10772 {},
10773 0,
10774 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010775
10776 // Let second display has a touch state.
10777 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010778 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010779 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10780 AINPUT_SOURCE_TOUCHSCREEN)
10781 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010782 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000010783 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000010784 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010785 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010786 mDispatcher->onWindowInfosChanged(
10787 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10788 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10789 {},
10790 0,
10791 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010792
10793 // Move on window.
10794 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010795 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010796 ADISPLAY_ID_DEFAULT, {50, 50}))
10797 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10798 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10799 mWindow->consumeDragEvent(false, 50, 50);
10800 mSecondWindow->assertNoEvents();
10801
10802 // Move to another window.
10803 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010804 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010805 ADISPLAY_ID_DEFAULT, {150, 50}))
10806 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10807 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10808 mWindow->consumeDragEvent(true, 150, 50);
10809 mSecondWindow->consumeDragEvent(false, 50, 50);
10810
10811 // drop to another window.
10812 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010813 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010814 {150, 50}))
10815 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10816 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010817 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000010818 mWindow->assertNoEvents();
10819 mSecondWindow->assertNoEvents();
10820}
10821
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010822TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
10823 startDrag(true, AINPUT_SOURCE_MOUSE);
10824 // Move on window.
10825 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010826 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010827 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10828 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010829 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010830 .x(50)
10831 .y(50))
10832 .build()))
10833 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10834 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10835 mWindow->consumeDragEvent(false, 50, 50);
10836 mSecondWindow->assertNoEvents();
10837
10838 // Move to another window.
10839 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010840 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010841 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10842 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010843 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010844 .x(150)
10845 .y(50))
10846 .build()))
10847 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10848 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10849 mWindow->consumeDragEvent(true, 150, 50);
10850 mSecondWindow->consumeDragEvent(false, 50, 50);
10851
10852 // drop to another window.
10853 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010854 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010855 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
10856 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010857 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010858 .x(150)
10859 .y(50))
10860 .build()))
10861 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10862 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010863 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010864 mWindow->assertNoEvents();
10865 mSecondWindow->assertNoEvents();
10866}
10867
Linnan Li5af92f92023-07-14 14:36:22 +080010868/**
10869 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
10870 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
10871 */
10872TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
10873 // Down on second window
10874 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10875 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10876 {150, 50}))
10877 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10878
10879 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
10880 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
10881
10882 // Down on first window
10883 const MotionEvent secondFingerDownEvent =
10884 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10885 .displayId(ADISPLAY_ID_DEFAULT)
10886 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10887 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10888 .build();
10889 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10890 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10891 InputEventInjectionSync::WAIT_FOR_RESULT))
10892 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10893 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10894 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
10895 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
10896
10897 // Start drag on first window
10898 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
10899
10900 // Trigger cancel
10901 mDispatcher->cancelCurrentTouch();
10902 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
10903 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
10904 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
10905
10906 ASSERT_TRUE(mDispatcher->waitForIdle());
10907 // The D&D finished with nullptr
10908 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
10909
10910 // Remove drag window
10911 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
10912
10913 // Inject a simple gesture, ensure dispatcher not crashed
10914 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10915 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10916 PointF{50, 50}))
10917 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10918 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10919
10920 const MotionEvent moveEvent =
10921 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10922 .displayId(ADISPLAY_ID_DEFAULT)
10923 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10924 .build();
10925 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10926 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
10927 InputEventInjectionSync::WAIT_FOR_RESULT))
10928 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10929 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
10930
10931 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10932 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10933 {50, 50}))
10934 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10935 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
10936}
10937
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000010938TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
10939 // Start hovering over the window.
10940 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10941 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
10942 ADISPLAY_ID_DEFAULT, {50, 50}));
10943
10944 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10945 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10946
10947 ASSERT_FALSE(startDrag(/*sendDown=*/false))
10948 << "Drag and drop should not work with a hovering pointer";
10949}
10950
Vishnu Nair062a8672021-09-03 16:07:44 -070010951class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
10952
10953TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
10954 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010955 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10956 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010957 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010958 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10959 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010960 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010961 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010962 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010963
10964 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010965 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010966 window->assertNoEvents();
10967
Prabir Pradhan678438e2023-04-13 19:32:51 +000010968 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10969 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010970 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10971 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080010972 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070010973 window->assertNoEvents();
10974
10975 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010976 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010977 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010978
Prabir Pradhan678438e2023-04-13 19:32:51 +000010979 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010980 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10981
Prabir Pradhan678438e2023-04-13 19:32:51 +000010982 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10983 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010984 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10985 window->assertNoEvents();
10986}
10987
10988TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
10989 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10990 std::make_shared<FakeApplicationHandle>();
10991 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010992 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10993 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010994 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010995 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010996 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010997 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010998 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10999 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011000 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011001 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070011002 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
11003 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011004 mDispatcher->onWindowInfosChanged(
11005 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011006 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011007 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011008
11009 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000011010 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011011 window->assertNoEvents();
11012
Prabir Pradhan678438e2023-04-13 19:32:51 +000011013 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11014 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070011015 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
11016 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011017 window->assertNoEvents();
11018
11019 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011020 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011021 mDispatcher->onWindowInfosChanged(
11022 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011023
Prabir Pradhan678438e2023-04-13 19:32:51 +000011024 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011025 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
11026
Prabir Pradhan678438e2023-04-13 19:32:51 +000011027 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11028 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011029 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
11030 window->assertNoEvents();
11031}
11032
11033TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
11034 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
11035 std::make_shared<FakeApplicationHandle>();
11036 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011037 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
11038 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070011039 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011040 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011041 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070011042 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011043 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
11044 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011045 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011046 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070011047 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
11048 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011049 mDispatcher->onWindowInfosChanged(
11050 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011051 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011052 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011053
11054 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000011055 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011056 window->assertNoEvents();
11057
Prabir Pradhan678438e2023-04-13 19:32:51 +000011058 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11059 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070011060 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
11061 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011062 window->assertNoEvents();
11063
11064 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011065 mDispatcher->onWindowInfosChanged(
11066 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011067
Prabir Pradhan678438e2023-04-13 19:32:51 +000011068 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011069 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
11070
Prabir Pradhan678438e2023-04-13 19:32:51 +000011071 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11072 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011073 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11074 window->assertNoEvents();
11075}
11076
Antonio Kantekf16f2832021-09-28 04:39:20 +000011077class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
11078protected:
11079 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000011080 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000011081 sp<FakeWindowHandle> mWindow;
11082 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000011083 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000011084
11085 void SetUp() override {
11086 InputDispatcherTest::SetUp();
11087
11088 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000011089 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011090 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011091 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011092 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011093 mSecondWindow =
11094 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011095 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000011096 mThirdWindow =
11097 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
11098 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
11099 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011100
11101 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011102 mDispatcher->onWindowInfosChanged(
11103 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
11104 {},
11105 0,
11106 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000011107 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011108 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011109
Antonio Kantek15beb512022-06-13 22:35:41 +000011110 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000011111 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000011112 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070011113 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
11114 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000011115 mThirdWindow->assertNoEvents();
11116 }
11117
11118 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
11119 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000011120 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000011121 SECOND_DISPLAY_ID)) {
11122 mWindow->assertNoEvents();
11123 mSecondWindow->assertNoEvents();
11124 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070011125 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000011126 }
11127
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011128 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000011129 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070011130 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
11131 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000011132 mWindow->consumeTouchModeEvent(inTouchMode);
11133 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000011134 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000011135 }
11136};
11137
Antonio Kantek26defcf2022-02-08 01:12:27 +000011138TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080011139 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000011140 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
11141 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011142 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011143}
11144
Antonio Kantek26defcf2022-02-08 01:12:27 +000011145TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
11146 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011147 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011148 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011149 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011150 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000011151 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -070011152 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000011153 mWindow->assertNoEvents();
11154 mSecondWindow->assertNoEvents();
11155}
11156
11157TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
11158 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011159 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011160 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011161 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000011162 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000011163 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011164}
11165
Antonio Kantekf16f2832021-09-28 04:39:20 +000011166TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080011167 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000011168 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
11169 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011170 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000011171 mWindow->assertNoEvents();
11172 mSecondWindow->assertNoEvents();
11173}
11174
Antonio Kantek15beb512022-06-13 22:35:41 +000011175TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
11176 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
11177 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
11178 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011179 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000011180 mWindow->assertNoEvents();
11181 mSecondWindow->assertNoEvents();
11182 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
11183}
11184
Antonio Kantek48710e42022-03-24 14:19:30 -070011185TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
11186 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011187 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11188 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070011189 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11190 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
11191
11192 // Then remove focus.
11193 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011194 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070011195
11196 // Assert that caller can switch touch mode by owning one of the last interacted window.
11197 const WindowInfo& windowInfo = *mWindow->getInfo();
11198 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
11199 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011200 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070011201}
11202
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011203class InputDispatcherSpyWindowTest : public InputDispatcherTest {
11204public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011205 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011206 std::shared_ptr<FakeApplicationHandle> application =
11207 std::make_shared<FakeApplicationHandle>();
11208 std::string name = "Fake Spy ";
11209 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011210 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
11211 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011212 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011213 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011214 return spy;
11215 }
11216
11217 sp<FakeWindowHandle> createForeground() {
11218 std::shared_ptr<FakeApplicationHandle> application =
11219 std::make_shared<FakeApplicationHandle>();
11220 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011221 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
11222 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011223 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011224 return window;
11225 }
11226
11227private:
11228 int mSpyCount{0};
11229};
11230
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011231using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011232/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011233 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
11234 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011235TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070011236 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011237 ScopedSilentDeath _silentDeath;
11238
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011239 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011240 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011241 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011242 ".* not a trusted overlay");
11243}
11244
11245/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011246 * Input injection into a display with a spy window but no foreground windows should succeed.
11247 */
11248TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011249 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011250 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011251
11252 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011253 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011254 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11255 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11256}
11257
11258/**
11259 * Verify the order in which different input windows receive events. The touched foreground window
11260 * (if there is one) should always receive the event first. When there are multiple spy windows, the
11261 * spy windows will receive the event according to their Z-order, where the top-most spy window will
11262 * receive events before ones belows it.
11263 *
11264 * Here, we set up a scenario with four windows in the following Z order from the top:
11265 * spy1, spy2, window, spy3.
11266 * We then inject an event and verify that the foreground "window" receives it first, followed by
11267 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
11268 * window.
11269 */
11270TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
11271 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011272 auto spy1 = createSpy();
11273 auto spy2 = createSpy();
11274 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011275 mDispatcher->onWindowInfosChanged(
11276 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011277 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
11278 const size_t numChannels = channels.size();
11279
Michael Wright8e9a8562022-02-09 13:44:29 +000011280 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011281 if (!epollFd.ok()) {
11282 FAIL() << "Failed to create epoll fd";
11283 }
11284
11285 for (size_t i = 0; i < numChannels; i++) {
11286 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
11287 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
11288 FAIL() << "Failed to add fd to epoll";
11289 }
11290 }
11291
11292 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011293 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011294 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11295
11296 std::vector<size_t> eventOrder;
11297 std::vector<struct epoll_event> events(numChannels);
11298 for (;;) {
11299 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
11300 (100ms).count());
11301 if (nFds < 0) {
11302 FAIL() << "Failed to call epoll_wait";
11303 }
11304 if (nFds == 0) {
11305 break; // epoll_wait timed out
11306 }
11307 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070011308 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070011309 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011310 channels[i]->consumeMotionDown();
11311 }
11312 }
11313
11314 // Verify the order in which the events were received.
11315 EXPECT_EQ(3u, eventOrder.size());
11316 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
11317 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
11318 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
11319}
11320
11321/**
11322 * A spy window using the NOT_TOUCHABLE flag does not receive events.
11323 */
11324TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
11325 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011326 auto spy = createSpy();
11327 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011328 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011329
11330 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011331 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011332 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11333 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11334 spy->assertNoEvents();
11335}
11336
11337/**
11338 * A spy window will only receive gestures that originate within its touchable region. Gestures that
11339 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
11340 * to the window.
11341 */
11342TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
11343 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011344 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011345 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011346 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011347
11348 // Inject an event outside the spy window's touchable region.
11349 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011350 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011351 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11352 window->consumeMotionDown();
11353 spy->assertNoEvents();
11354 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011355 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011356 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11357 window->consumeMotionUp();
11358 spy->assertNoEvents();
11359
11360 // Inject an event inside the spy window's touchable region.
11361 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011362 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011363 {5, 10}))
11364 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11365 window->consumeMotionDown();
11366 spy->consumeMotionDown();
11367}
11368
11369/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011370 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011371 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011372 */
11373TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
11374 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011375 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011376 auto spy = createSpy();
11377 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011378 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011379 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011380 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011381
11382 // Inject an event outside the spy window's frame and touchable region.
11383 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011384 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011385 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011386 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11387 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011388 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011389}
11390
11391/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011392 * Even when a spy window spans over multiple foreground windows, the spy should receive all
11393 * pointers that are down within its bounds.
11394 */
11395TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
11396 auto windowLeft = createForeground();
11397 windowLeft->setFrame({0, 0, 100, 200});
11398 auto windowRight = createForeground();
11399 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011400 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011401 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011402 mDispatcher->onWindowInfosChanged(
11403 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011404
11405 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011406 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011407 {50, 50}))
11408 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11409 windowLeft->consumeMotionDown();
11410 spy->consumeMotionDown();
11411
11412 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011413 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011414 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011415 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11416 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011417 .build();
11418 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011419 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011420 InputEventInjectionSync::WAIT_FOR_RESULT))
11421 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11422 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000011423 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011424}
11425
11426/**
11427 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
11428 * the spy should receive the second pointer with ACTION_DOWN.
11429 */
11430TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
11431 auto window = createForeground();
11432 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011433 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011434 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011435 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011436
11437 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011438 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011439 {50, 50}))
11440 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11441 window->consumeMotionDown();
11442 spyRight->assertNoEvents();
11443
11444 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011445 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011446 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011447 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11448 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011449 .build();
11450 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011451 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011452 InputEventInjectionSync::WAIT_FOR_RESULT))
11453 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000011454 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011455 spyRight->consumeMotionDown();
11456}
11457
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011458/**
11459 * The spy window should not be able to affect whether or not touches are split. Only the foreground
11460 * windows should be allowed to control split touch.
11461 */
11462TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080011463 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011464 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011465 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080011466 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011467
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011468 auto window = createForeground();
11469 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011470
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011471 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011472
11473 // First finger down, no window touched.
11474 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011475 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011476 {100, 200}))
11477 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11478 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11479 window->assertNoEvents();
11480
11481 // Second finger down on window, the window should receive touch down.
11482 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011483 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011484 .displayId(ADISPLAY_ID_DEFAULT)
11485 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011486 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11487 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011488 .build();
11489 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011490 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011491 InputEventInjectionSync::WAIT_FOR_RESULT))
11492 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11493
11494 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000011495 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011496}
11497
11498/**
11499 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
11500 * do not receive key events.
11501 */
11502TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011503 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011504 spy->setFocusable(false);
11505
11506 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011507 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011508 setFocusedWindow(window);
11509 window->consumeFocusEvent(true);
11510
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011511 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011512 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11513 window->consumeKeyDown(ADISPLAY_ID_NONE);
11514
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011515 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011516 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11517 window->consumeKeyUp(ADISPLAY_ID_NONE);
11518
11519 spy->assertNoEvents();
11520}
11521
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011522using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
11523
11524/**
11525 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
11526 * are currently sent to any other windows - including other spy windows - will also be cancelled.
11527 */
11528TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
11529 auto window = createForeground();
11530 auto spy1 = createSpy();
11531 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011532 mDispatcher->onWindowInfosChanged(
11533 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011534
11535 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011536 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011537 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11538 window->consumeMotionDown();
11539 spy1->consumeMotionDown();
11540 spy2->consumeMotionDown();
11541
11542 // Pilfer pointers from the second spy window.
11543 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
11544 spy2->assertNoEvents();
11545 spy1->consumeMotionCancel();
11546 window->consumeMotionCancel();
11547
11548 // The rest of the gesture should only be sent to the second spy window.
11549 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011550 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011551 ADISPLAY_ID_DEFAULT))
11552 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11553 spy2->consumeMotionMove();
11554 spy1->assertNoEvents();
11555 window->assertNoEvents();
11556}
11557
11558/**
11559 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
11560 * in the middle of the gesture.
11561 */
11562TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
11563 auto window = createForeground();
11564 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011565 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011566
11567 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011568 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011569 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11570 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11571 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11572
11573 window->releaseChannel();
11574
11575 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11576
11577 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011578 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011579 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11580 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
11581}
11582
11583/**
11584 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
11585 * the spy, but not to any other windows.
11586 */
11587TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
11588 auto spy = createSpy();
11589 auto window = createForeground();
11590
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011591 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011592
11593 // First finger down on the window and the spy.
11594 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011595 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011596 {100, 200}))
11597 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11598 spy->consumeMotionDown();
11599 window->consumeMotionDown();
11600
11601 // Spy window pilfers the pointers.
11602 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11603 window->consumeMotionCancel();
11604
11605 // Second finger down on the window and spy, but the window should not receive the pointer down.
11606 const MotionEvent secondFingerDownEvent =
11607 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11608 .displayId(ADISPLAY_ID_DEFAULT)
11609 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011610 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11611 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011612 .build();
11613 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011614 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011615 InputEventInjectionSync::WAIT_FOR_RESULT))
11616 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11617
Harry Cutts33476232023-01-30 19:57:29 +000011618 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011619
11620 // Third finger goes down outside all windows, so injection should fail.
11621 const MotionEvent thirdFingerDownEvent =
11622 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11623 .displayId(ADISPLAY_ID_DEFAULT)
11624 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011625 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11626 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
11627 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011628 .build();
11629 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011630 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011631 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080011632 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011633
11634 spy->assertNoEvents();
11635 window->assertNoEvents();
11636}
11637
11638/**
11639 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
11640 */
11641TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
11642 auto spy = createSpy();
11643 spy->setFrame(Rect(0, 0, 100, 100));
11644 auto window = createForeground();
11645 window->setFrame(Rect(0, 0, 200, 200));
11646
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011647 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011648
11649 // First finger down on the window only
11650 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011651 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011652 {150, 150}))
11653 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11654 window->consumeMotionDown();
11655
11656 // Second finger down on the spy and window
11657 const MotionEvent secondFingerDownEvent =
11658 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11659 .displayId(ADISPLAY_ID_DEFAULT)
11660 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011661 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11662 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011663 .build();
11664 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011665 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011666 InputEventInjectionSync::WAIT_FOR_RESULT))
11667 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11668 spy->consumeMotionDown();
11669 window->consumeMotionPointerDown(1);
11670
11671 // Third finger down on the spy and window
11672 const MotionEvent thirdFingerDownEvent =
11673 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11674 .displayId(ADISPLAY_ID_DEFAULT)
11675 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011676 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11677 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
11678 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011679 .build();
11680 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011681 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011682 InputEventInjectionSync::WAIT_FOR_RESULT))
11683 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11684 spy->consumeMotionPointerDown(1);
11685 window->consumeMotionPointerDown(2);
11686
11687 // Spy window pilfers the pointers.
11688 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000011689 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
11690 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011691
11692 spy->assertNoEvents();
11693 window->assertNoEvents();
11694}
11695
11696/**
11697 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
11698 * other windows should be canceled. If this results in the cancellation of all pointers for some
11699 * window, then that window should receive ACTION_CANCEL.
11700 */
11701TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
11702 auto spy = createSpy();
11703 spy->setFrame(Rect(0, 0, 100, 100));
11704 auto window = createForeground();
11705 window->setFrame(Rect(0, 0, 200, 200));
11706
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011707 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011708
11709 // First finger down on both spy and window
11710 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011711 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011712 {10, 10}))
11713 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11714 window->consumeMotionDown();
11715 spy->consumeMotionDown();
11716
11717 // Second finger down on the spy and window
11718 const MotionEvent secondFingerDownEvent =
11719 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11720 .displayId(ADISPLAY_ID_DEFAULT)
11721 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011722 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11723 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011724 .build();
11725 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011726 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011727 InputEventInjectionSync::WAIT_FOR_RESULT))
11728 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11729 spy->consumeMotionPointerDown(1);
11730 window->consumeMotionPointerDown(1);
11731
11732 // Spy window pilfers the pointers.
11733 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11734 window->consumeMotionCancel();
11735
11736 spy->assertNoEvents();
11737 window->assertNoEvents();
11738}
11739
11740/**
11741 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
11742 * be sent to other windows
11743 */
11744TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
11745 auto spy = createSpy();
11746 spy->setFrame(Rect(0, 0, 100, 100));
11747 auto window = createForeground();
11748 window->setFrame(Rect(0, 0, 200, 200));
11749
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011750 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011751
11752 // First finger down on both window and spy
11753 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011754 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011755 {10, 10}))
11756 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11757 window->consumeMotionDown();
11758 spy->consumeMotionDown();
11759
11760 // Spy window pilfers the pointers.
11761 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11762 window->consumeMotionCancel();
11763
11764 // Second finger down on the window only
11765 const MotionEvent secondFingerDownEvent =
11766 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11767 .displayId(ADISPLAY_ID_DEFAULT)
11768 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011769 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11770 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011771 .build();
11772 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011773 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011774 InputEventInjectionSync::WAIT_FOR_RESULT))
11775 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11776 window->consumeMotionDown();
11777 window->assertNoEvents();
11778
11779 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
11780 spy->consumeMotionMove();
11781 spy->assertNoEvents();
11782}
11783
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011784/**
11785 * A window on the left and a window on the right. Also, a spy window that's above all of the
11786 * windows, and spanning both left and right windows.
11787 * Send simultaneous motion streams from two different devices, one to the left window, and another
11788 * to the right window.
11789 * Pilfer from spy window.
11790 * Check that the pilfering only affects the pointers that are actually being received by the spy.
11791 */
11792TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
11793 sp<FakeWindowHandle> spy = createSpy();
11794 spy->setFrame(Rect(0, 0, 200, 200));
11795 sp<FakeWindowHandle> leftWindow = createForeground();
11796 leftWindow->setFrame(Rect(0, 0, 100, 100));
11797
11798 sp<FakeWindowHandle> rightWindow = createForeground();
11799 rightWindow->setFrame(Rect(100, 0, 200, 100));
11800
11801 constexpr int32_t stylusDeviceId = 1;
11802 constexpr int32_t touchDeviceId = 2;
11803
11804 mDispatcher->onWindowInfosChanged(
11805 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
11806
11807 // Stylus down on left window and spy
11808 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
11809 .deviceId(stylusDeviceId)
11810 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
11811 .build());
11812 leftWindow->consumeMotionEvent(
11813 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11814 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11815
11816 // Finger down on right window and spy - but spy already has stylus
11817 mDispatcher->notifyMotion(
11818 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11819 .deviceId(touchDeviceId)
11820 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
11821 .build());
11822 rightWindow->consumeMotionEvent(
11823 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011824 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011825
11826 // Act: pilfer from spy. Spy is currently receiving touch events.
11827 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011828 leftWindow->consumeMotionEvent(
11829 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011830 rightWindow->consumeMotionEvent(
11831 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
11832
11833 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
11834 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
11835 .deviceId(stylusDeviceId)
11836 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
11837 .build());
11838 mDispatcher->notifyMotion(
11839 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
11840 .deviceId(touchDeviceId)
11841 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
11842 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011843 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011844
11845 spy->assertNoEvents();
11846 leftWindow->assertNoEvents();
11847 rightWindow->assertNoEvents();
11848}
11849
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000011850TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
11851 auto window = createForeground();
11852 auto spy = createSpy();
11853 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
11854
11855 mDispatcher->notifyMotion(
11856 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11857 .deviceId(1)
11858 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
11859 .build());
11860 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11861 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11862
11863 // Pilfer pointers from the spy window should fail.
11864 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
11865 spy->assertNoEvents();
11866 window->assertNoEvents();
11867}
11868
Prabir Pradhand65552b2021-10-07 11:23:50 -070011869class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
11870public:
11871 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
11872 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11873 std::make_shared<FakeApplicationHandle>();
11874 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011875 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11876 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011877 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011878 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011879 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011880 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011881 overlay->setTrustedOverlay(true);
11882
11883 std::shared_ptr<FakeApplicationHandle> application =
11884 std::make_shared<FakeApplicationHandle>();
11885 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011886 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
11887 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011888 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011889 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011890
11891 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011892 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011893 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011894 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011895 return {std::move(overlay), std::move(window)};
11896 }
11897
11898 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011899 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070011900 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000011901 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070011902 }
11903
11904 void sendStylusEvent(int32_t action) {
11905 NotifyMotionArgs motionArgs =
11906 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
11907 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011908 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000011909 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011910 }
11911};
11912
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011913using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
11914
11915TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070011916 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011917 ScopedSilentDeath _silentDeath;
11918
Prabir Pradhand65552b2021-10-07 11:23:50 -070011919 auto [overlay, window] = setupStylusOverlayScenario();
11920 overlay->setTrustedOverlay(false);
11921 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011922 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
11923 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070011924 ".* not a trusted overlay");
11925}
11926
11927TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
11928 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011929 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011930
11931 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11932 overlay->consumeMotionDown();
11933 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11934 overlay->consumeMotionUp();
11935
11936 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11937 window->consumeMotionDown();
11938 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11939 window->consumeMotionUp();
11940
11941 overlay->assertNoEvents();
11942 window->assertNoEvents();
11943}
11944
11945TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
11946 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011947 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011948 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011949
11950 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11951 overlay->consumeMotionDown();
11952 window->consumeMotionDown();
11953 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11954 overlay->consumeMotionUp();
11955 window->consumeMotionUp();
11956
11957 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11958 window->consumeMotionDown();
11959 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11960 window->consumeMotionUp();
11961
11962 overlay->assertNoEvents();
11963 window->assertNoEvents();
11964}
11965
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011966/**
11967 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
11968 * The scenario is as follows:
11969 * - The stylus interceptor overlay is configured as a spy window.
11970 * - The stylus interceptor spy receives the start of a new stylus gesture.
11971 * - It pilfers pointers and then configures itself to no longer be a spy.
11972 * - The stylus interceptor continues to receive the rest of the gesture.
11973 */
11974TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
11975 auto [overlay, window] = setupStylusOverlayScenario();
11976 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011977 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011978
11979 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11980 overlay->consumeMotionDown();
11981 window->consumeMotionDown();
11982
11983 // The interceptor pilfers the pointers.
11984 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
11985 window->consumeMotionCancel();
11986
11987 // The interceptor configures itself so that it is no longer a spy.
11988 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011989 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011990
11991 // It continues to receive the rest of the stylus gesture.
11992 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
11993 overlay->consumeMotionMove();
11994 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11995 overlay->consumeMotionUp();
11996
11997 window->assertNoEvents();
11998}
11999
Prabir Pradhan5735a322022-04-11 17:23:34 +000012000struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012001 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000012002 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000012003 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
12004 std::unique_ptr<InputDispatcher>& mDispatcher;
12005
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012006 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000012007 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
12008
12009 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012010 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000012011 ADISPLAY_ID_DEFAULT, {100, 200},
12012 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
12013 AMOTION_EVENT_INVALID_CURSOR_POSITION},
12014 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
12015 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
12016 }
12017
12018 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012019 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000012020 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000012021 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000012022 mPolicyFlags);
12023 }
12024
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012025 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000012026 std::shared_ptr<FakeApplicationHandle> overlayApplication =
12027 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012028 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
12029 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000012030 window->setOwnerInfo(mPid, mUid);
12031 return window;
12032 }
12033};
12034
12035using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
12036
12037TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012038 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012039 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012040 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012041
12042 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12043 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12044 window->consumeMotionDown();
12045
12046 setFocusedWindow(window);
12047 window->consumeFocusEvent(true);
12048
12049 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12050 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
12051 window->consumeKeyDown(ADISPLAY_ID_NONE);
12052}
12053
12054TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012055 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012056 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012057 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012058
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012059 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012060 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
12061 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12062
12063 setFocusedWindow(window);
12064 window->consumeFocusEvent(true);
12065
12066 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
12067 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
12068 window->assertNoEvents();
12069}
12070
12071TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012072 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012073 auto window = owner.createWindow("Owned window");
12074 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012075 spy->setSpy(true);
12076 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012077 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012078
12079 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12080 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12081 spy->consumeMotionDown();
12082 window->consumeMotionDown();
12083}
12084
12085TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012086 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012087 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012088
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012089 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012090 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012091 randosSpy->setSpy(true);
12092 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012093 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012094
12095 // The event is targeted at owner's window, so injection should succeed, but the spy should
12096 // not receive the event.
12097 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12098 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12099 randosSpy->assertNoEvents();
12100 window->consumeMotionDown();
12101}
12102
12103TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012104 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012105 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012106
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012107 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012108 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012109 randosSpy->setSpy(true);
12110 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012111 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012112
12113 // A user that has injection permission can inject into any window.
12114 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012115 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000012116 ADISPLAY_ID_DEFAULT));
12117 randosSpy->consumeMotionDown();
12118 window->consumeMotionDown();
12119
12120 setFocusedWindow(randosSpy);
12121 randosSpy->consumeFocusEvent(true);
12122
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012123 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000012124 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
12125 window->assertNoEvents();
12126}
12127
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012128TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012129 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012130 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012131
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012132 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012133 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012134 randosWindow->setFrame(Rect{-10, -10, -5, -5});
12135 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012136 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012137
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012138 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000012139 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12140 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12141 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012142 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000012143}
12144
Prabir Pradhan64f21d22023-11-28 21:19:42 +000012145using InputDispatcherPointerInWindowTest = InputDispatcherTest;
12146
12147TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
12148 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12149
12150 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12151 ADISPLAY_ID_DEFAULT);
12152 left->setFrame(Rect(0, 0, 100, 100));
12153 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12154 "Right Window", ADISPLAY_ID_DEFAULT);
12155 right->setFrame(Rect(100, 0, 200, 100));
12156 sp<FakeWindowHandle> spy =
12157 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
12158 spy->setFrame(Rect(0, 0, 200, 100));
12159 spy->setTrustedOverlay(true);
12160 spy->setSpy(true);
12161
12162 mDispatcher->onWindowInfosChanged(
12163 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
12164
12165 // Hover into the left window.
12166 mDispatcher->notifyMotion(
12167 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
12168 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
12169 .build());
12170
12171 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12172 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12173
12174 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12175 /*pointerId=*/0));
12176 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12177 /*pointerId=*/0));
12178 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12179 /*pointerId=*/0));
12180
12181 // Hover move to the right window.
12182 mDispatcher->notifyMotion(
12183 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
12184 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
12185 .build());
12186
12187 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12188 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12189 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
12190
12191 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12192 /*pointerId=*/0));
12193 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12194 /*pointerId=*/0));
12195 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12196 /*pointerId=*/0));
12197
12198 // Stop hovering.
12199 mDispatcher->notifyMotion(
12200 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
12201 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
12202 .build());
12203
12204 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12205 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12206
12207 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12208 /*pointerId=*/0));
12209 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12210 /*pointerId=*/0));
12211 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12212 /*pointerId=*/0));
12213}
12214
12215TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
12216 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12217
12218 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12219 ADISPLAY_ID_DEFAULT);
12220 left->setFrame(Rect(0, 0, 100, 100));
12221 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12222 "Right Window", ADISPLAY_ID_DEFAULT);
12223 right->setFrame(Rect(100, 0, 200, 100));
12224 sp<FakeWindowHandle> spy =
12225 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
12226 spy->setFrame(Rect(0, 0, 200, 100));
12227 spy->setTrustedOverlay(true);
12228 spy->setSpy(true);
12229
12230 mDispatcher->onWindowInfosChanged(
12231 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
12232
12233 // First pointer down on left window.
12234 mDispatcher->notifyMotion(
12235 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12236 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12237 .build());
12238
12239 left->consumeMotionDown();
12240 spy->consumeMotionDown();
12241
12242 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12243 /*pointerId=*/0));
12244 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12245 /*pointerId=*/0));
12246 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12247 /*pointerId=*/0));
12248
12249 // Second pointer down on right window.
12250 mDispatcher->notifyMotion(
12251 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12252 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12253 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
12254 .build());
12255
12256 left->consumeMotionMove();
12257 right->consumeMotionDown();
12258 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
12259
12260 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12261 /*pointerId=*/0));
12262 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12263 /*pointerId=*/0));
12264 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12265 /*pointerId=*/0));
12266 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12267 /*pointerId=*/1));
12268 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12269 /*pointerId=*/1));
12270 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12271 /*pointerId=*/1));
12272
12273 // Second pointer up.
12274 mDispatcher->notifyMotion(
12275 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
12276 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12277 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
12278 .build());
12279
12280 left->consumeMotionMove();
12281 right->consumeMotionUp();
12282 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
12283
12284 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12285 /*pointerId=*/0));
12286 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12287 /*pointerId=*/0));
12288 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12289 /*pointerId=*/0));
12290 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12291 /*pointerId=*/1));
12292 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12293 /*pointerId=*/1));
12294 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12295 /*pointerId=*/1));
12296
12297 // First pointer up.
12298 mDispatcher->notifyMotion(
12299 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
12300 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12301 .build());
12302
12303 left->consumeMotionUp();
12304 spy->consumeMotionUp();
12305
12306 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12307 /*pointerId=*/0));
12308 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12309 /*pointerId=*/0));
12310 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12311 /*pointerId=*/0));
12312}
12313
12314TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
12315 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12316
12317 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12318 ADISPLAY_ID_DEFAULT);
12319 left->setFrame(Rect(0, 0, 100, 100));
12320 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12321 "Right Window", ADISPLAY_ID_DEFAULT);
12322 right->setFrame(Rect(100, 0, 200, 100));
12323
12324 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
12325
12326 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12327 /*pointerId=*/0));
12328 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12329 /*pointerId=*/0));
12330
12331 // Hover move into the window.
12332 mDispatcher->notifyMotion(
12333 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12334 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
12335 .rawXCursorPosition(50)
12336 .rawYCursorPosition(50)
12337 .deviceId(DEVICE_ID)
12338 .build());
12339
12340 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12341
12342 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12343 /*pointerId=*/0));
12344
12345 // Move the mouse with another device. This cancels the hovering pointer from the first device.
12346 mDispatcher->notifyMotion(
12347 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12348 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
12349 .rawXCursorPosition(51)
12350 .rawYCursorPosition(50)
12351 .deviceId(SECOND_DEVICE_ID)
12352 .build());
12353
12354 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12355 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12356
12357 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
12358 // a HOVER_EXIT from the first device.
12359 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12360 /*pointerId=*/0));
12361 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
12362 SECOND_DEVICE_ID,
12363 /*pointerId=*/0));
12364
12365 // Move the mouse outside the window. Document the current behavior, where the window does not
12366 // receive HOVER_EXIT even though the mouse left the window.
12367 mDispatcher->notifyMotion(
12368 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12369 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
12370 .rawXCursorPosition(150)
12371 .rawYCursorPosition(50)
12372 .deviceId(SECOND_DEVICE_ID)
12373 .build());
12374
12375 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12376 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12377 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12378 /*pointerId=*/0));
12379 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
12380 SECOND_DEVICE_ID,
12381 /*pointerId=*/0));
12382}
12383
Garfield Tane84e6f92019-08-29 17:28:41 -070012384} // namespace android::inputdispatcher