blob: 31c7c67db50a2b4e740a2382b0ca6a8362b163f8 [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000018#include "../BlockingQueue.h"
Siarhei Vishniakou2defec02023-06-08 17:24:44 -070019#include "FakeApplicationHandle.h"
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +000020#include "FakeInputTracingBackend.h"
Prabir Pradhane3b28dd2023-10-06 04:19:29 +000021#include "TestEventMatchers.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080022
Cody Heiner166a5af2023-07-07 12:25:00 -070023#include <NotifyArgsBuilders.h>
Prabir Pradhan5893d362023-11-17 04:30:40 +000024#include <android-base/logging.h>
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070025#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080026#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080027#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070028#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070029#include <binder/Binder.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000030#include <com_android_input_flags.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000031#include <fcntl.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000032#include <flag_macros.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080033#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080034#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100035#include <input/Input.h>
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070036#include <input/PrintTools.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080037#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080038#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100039
Garfield Tan1c7bc862020-01-28 13:24:04 -080040#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080041#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070042#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080043#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080044#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080045
Garfield Tan1c7bc862020-01-28 13:24:04 -080046using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050047using android::gui::FocusRequest;
48using android::gui::TouchOcclusionMode;
49using android::gui::WindowInfo;
50using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080051using android::os::InputEventInjectionResult;
52using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080053
Garfield Tane84e6f92019-08-29 17:28:41 -070054namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080055
Dominik Laskowski2f01d772022-03-23 16:01:29 -070056using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080057using testing::AllOf;
Prabir Pradhan5893d362023-11-17 04:30:40 +000058using testing::Not;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070059
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070060namespace {
61
Michael Wrightd02c5b62014-02-10 15:10:22 -080062// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000063static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080064
65// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000066static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080067static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080068
Jeff Brownf086ddb2014-02-11 14:28:48 -080069// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000070static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
71static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080072
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000073// Ensure common actions are interchangeable between keys and motions for convenience.
74static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
75static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080076static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
77static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
78static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
79static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070080static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080081static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070082static constexpr int32_t ACTION_SCROLL = AMOTION_EVENT_ACTION_SCROLL;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080083static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080084static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080085/**
86 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
87 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
88 * index 0) is the new pointer going down. The same pointer could have been placed at a different
89 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
90 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
91 * pointer id=0 leaves but the pointer id=1 remains.
92 */
93static constexpr int32_t POINTER_0_DOWN =
94 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080095static constexpr int32_t POINTER_1_DOWN =
96 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000097static constexpr int32_t POINTER_2_DOWN =
98 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000099static constexpr int32_t POINTER_3_DOWN =
100 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +0000101static constexpr int32_t POINTER_0_UP =
102 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800103static constexpr int32_t POINTER_1_UP =
104 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +0000105static constexpr int32_t POINTER_2_UP =
106 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800107
Antonio Kantek15beb512022-06-13 22:35:41 +0000108// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000109static constexpr gui::Pid WINDOW_PID{999};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000110static constexpr gui::Uid WINDOW_UID{1001};
Prabir Pradhan5735a322022-04-11 17:23:34 +0000111
Antonio Kantek15beb512022-06-13 22:35:41 +0000112// The default pid and uid for the windows created on the secondary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000113static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000114static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000115
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000116// An arbitrary pid of the gesture monitor window
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000117static constexpr gui::Pid MONITOR_PID{2001};
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000118
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700119/**
120 * If we expect to receive the event, the timeout can be made very long. When the test are running
121 * correctly, we will actually never wait until the end of the timeout because the wait will end
122 * when the event comes in. Still, this value shouldn't be infinite. During development, a local
123 * change may cause the test to fail. This timeout should be short enough to not annoy so that the
124 * developer can see the failure quickly (on human scale).
125 */
126static constexpr std::chrono::duration CONSUME_TIMEOUT_EVENT_EXPECTED = 1000ms;
127/**
128 * When no event is expected, we can have a very short timeout. A large value here would slow down
129 * the tests. In the unlikely event of system being too slow, the event may still be present but the
130 * timeout would complete before it is consumed. This would result in test flakiness. If this
131 * occurs, the flakiness rate would be high. Since the flakes are treated with high priority, this
132 * would get noticed and addressed quickly.
133 */
134static constexpr std::chrono::duration CONSUME_TIMEOUT_NO_EVENT_EXPECTED = 10ms;
135
Arthur Hungc539dbb2022-12-08 07:45:36 +0000136static constexpr int expectedWallpaperFlags =
137 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
138
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800139using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
140
Gang Wang342c9272020-01-13 13:15:04 -0500141/**
142 * Return a DOWN key event with KEYCODE_A.
143 */
144static KeyEvent getTestKeyEvent() {
145 KeyEvent event;
146
Garfield Tanfbe732e2020-01-24 11:26:14 -0800147 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
148 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
149 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500150 return event;
151}
152
Michael Wrightd02c5b62014-02-10 15:10:22 -0800153// --- FakeInputDispatcherPolicy ---
154
155class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000156 struct AnrResult {
157 sp<IBinder> token{};
Prabir Pradhanfc364722024-02-08 17:51:20 +0000158 std::optional<gui::Pid> pid{};
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000159 };
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800160 /* Stores data about a user-activity-poke event from the dispatcher. */
161 struct UserActivityPokeEvent {
162 nsecs_t eventTime;
163 int32_t eventType;
164 int32_t displayId;
165
166 bool operator==(const UserActivityPokeEvent& rhs) const = default;
167
168 friend std::ostream& operator<<(std::ostream& os, const UserActivityPokeEvent& ev) {
169 os << "UserActivityPokeEvent[time=" << ev.eventTime << ", eventType=" << ev.eventType
170 << ", displayId=" << ev.displayId << "]";
171 return os;
172 }
173 };
Prabir Pradhanedd96402022-02-15 01:46:16 -0800174
Michael Wrightd02c5b62014-02-10 15:10:22 -0800175public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000176 FakeInputDispatcherPolicy() = default;
177 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800178
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800179 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700180 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700181 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700182 EXPECT_EQ(event.getDisplayId(), args.displayId);
183
184 const auto& keyEvent = static_cast<const KeyEvent&>(event);
185 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
186 EXPECT_EQ(keyEvent.getAction(), args.action);
187 });
Jackal Guof9696682018-10-05 12:23:23 +0800188 }
189
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700190 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
191 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700192 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700193 EXPECT_EQ(event.getDisplayId(), args.displayId);
194
195 const auto& motionEvent = static_cast<const MotionEvent&>(event);
196 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
197 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000198 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
199 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
200 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
201 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700202 });
Jackal Guof9696682018-10-05 12:23:23 +0800203 }
204
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700205 void assertFilterInputEventWasNotCalled() {
206 std::scoped_lock lock(mLock);
207 ASSERT_EQ(nullptr, mFilteredEvent);
208 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800209
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800210 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700211 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800212 ASSERT_TRUE(mConfigurationChangedTime)
213 << "Timed out waiting for configuration changed call";
214 ASSERT_EQ(*mConfigurationChangedTime, when);
215 mConfigurationChangedTime = std::nullopt;
216 }
217
218 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700219 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800220 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800221 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800222 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
223 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
224 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
225 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
226 mLastNotifySwitch = std::nullopt;
227 }
228
chaviwfd6d3512019-03-25 13:23:49 -0700229 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700230 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800231 ASSERT_EQ(touchedToken, mOnPointerDownToken);
232 mOnPointerDownToken.clear();
233 }
234
235 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700236 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800237 ASSERT_TRUE(mOnPointerDownToken == nullptr)
238 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700239 }
240
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700241 // This function must be called soon after the expected ANR timer starts,
242 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500243 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700244 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500245 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800246 std::unique_lock lock(mLock);
247 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500248 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800249 ASSERT_NO_FATAL_FAILURE(
250 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500251 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700252 }
253
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000254 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800255 const sp<WindowInfoHandle>& window) {
256 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
257 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
258 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500259 }
260
Prabir Pradhanedd96402022-02-15 01:46:16 -0800261 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
262 const sp<IBinder>& expectedToken,
Prabir Pradhanfc364722024-02-08 17:51:20 +0000263 std::optional<gui::Pid> expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800264 std::unique_lock lock(mLock);
265 android::base::ScopedLockAssertion assumeLocked(mLock);
266 AnrResult result;
267 ASSERT_NO_FATAL_FAILURE(result =
268 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000269 ASSERT_EQ(expectedToken, result.token);
270 ASSERT_EQ(expectedPid, result.pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500271 }
272
Prabir Pradhanedd96402022-02-15 01:46:16 -0800273 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000274 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500275 std::unique_lock lock(mLock);
276 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800277 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
278 const auto& [token, _] = result;
279 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000280 }
281
Prabir Pradhanedd96402022-02-15 01:46:16 -0800282 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
Prabir Pradhanfc364722024-02-08 17:51:20 +0000283 std::optional<gui::Pid> expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800284 std::unique_lock lock(mLock);
285 android::base::ScopedLockAssertion assumeLocked(mLock);
286 AnrResult result;
287 ASSERT_NO_FATAL_FAILURE(
288 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000289 ASSERT_EQ(expectedToken, result.token);
290 ASSERT_EQ(expectedPid, result.pid);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800291 }
292
293 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000294 sp<IBinder> getResponsiveWindowToken() {
295 std::unique_lock lock(mLock);
296 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800297 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
298 const auto& [token, _] = result;
299 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700300 }
301
302 void assertNotifyAnrWasNotCalled() {
303 std::scoped_lock lock(mLock);
304 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800305 ASSERT_TRUE(mAnrWindows.empty());
306 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500307 << "ANR was not called, but please also consume the 'connection is responsive' "
308 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700309 }
310
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 Pradhanfc364722024-02-08 17:51:20 +0000527 mAnrWindows.push({connectionToken, pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700528 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500529 }
530
Prabir Pradhanedd96402022-02-15 01:46:16 -0800531 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000532 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500533 std::scoped_lock lock(mLock);
Prabir Pradhanfc364722024-02-08 17:51:20 +0000534 mResponsiveWindows.push({connectionToken, pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500535 mNotifyAnr.notify_all();
536 }
537
538 void notifyNoFocusedWindowAnr(
539 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
540 std::scoped_lock lock(mLock);
541 mAnrApplications.push(applicationHandle);
542 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800543 }
544
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800545 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
546 std::scoped_lock lock(mLock);
547 mBrokenInputChannels.push(connectionToken);
548 mNotifyInputChannelBroken.notify_all();
549 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800550
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600551 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700552
Chris Yef59a2f42020-10-16 12:55:26 -0700553 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
554 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
555 const std::vector<float>& values) override {}
556
557 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
558 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000559
Chris Yefb552902021-02-03 17:18:37 -0800560 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
561
Prabir Pradhana41d2442023-04-20 21:30:40 +0000562 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700563 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000564 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700565 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000566 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
567 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800568 break;
569 }
570
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700571 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000572 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
573 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800574 break;
575 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700576 default: {
577 ADD_FAILURE() << "Should only filter keys or motions";
578 break;
579 }
Jackal Guof9696682018-10-05 12:23:23 +0800580 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800581 return true;
582 }
583
Prabir Pradhana41d2442023-04-20 21:30:40 +0000584 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
585 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800586 // Clear intercept state when we handled the event.
587 mInterceptKeyTimeout = 0ms;
588 }
589 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800590
Yeabkal Wubshit88a90412023-12-21 18:23:04 -0800591 void interceptMotionBeforeQueueing(int32_t, uint32_t, int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800592
Prabir Pradhana41d2442023-04-20 21:30:40 +0000593 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800594 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
595 // Clear intercept state so we could dispatch the event in next wake.
596 mInterceptKeyTimeout = 0ms;
597 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800598 }
599
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000600 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent& event,
Prabir Pradhana41d2442023-04-20 21:30:40 +0000601 uint32_t) override {
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000602 std::scoped_lock lock(mLock);
603 mReportedUnhandledKeycodes.emplace(event.getKeyCode());
604 mNotifyUnhandledKey.notify_all();
605 return mUnhandledKeyHandler != nullptr ? mUnhandledKeyHandler(event) : std::nullopt;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800606 }
607
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600608 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
609 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700610 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800611 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
612 * essentially a passthrough for notifySwitch.
613 */
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000614 mLastNotifySwitch =
615 NotifySwitchArgs(InputEvent::nextId(), when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800616 }
617
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800618 void pokeUserActivity(nsecs_t eventTime, int32_t eventType, int32_t displayId) override {
Josep del Riob3981622023-04-18 15:49:45 +0000619 std::scoped_lock lock(mLock);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800620 mNotifyUserActivity.notify_all();
621 mUserActivityPokeEvents.push({eventTime, eventType, displayId});
Josep del Riob3981622023-04-18 15:49:45 +0000622 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800623
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700624 bool isStaleEvent(nsecs_t currentTime, nsecs_t eventTime) override {
625 return std::chrono::nanoseconds(currentTime - eventTime) >= mStaleEventTimeout;
626 }
627
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600628 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700629 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700630 mOnPointerDownToken = newToken;
631 }
632
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000633 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800634 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000635 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800636 mPointerCaptureChangedCondition.notify_all();
637 }
638
arthurhungf452d0b2021-01-06 00:19:52 +0800639 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
640 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800641 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800642 mDropTargetWindowToken = token;
643 }
644
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000645 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000646 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000647 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
648 }
649
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700650 void assertFilterInputEventWasCalledInternal(
651 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700652 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800653 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700654 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800655 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800656 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800657};
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700658} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800659
Michael Wrightd02c5b62014-02-10 15:10:22 -0800660// --- InputDispatcherTest ---
661
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000662// The trace is a global variable for now, to avoid having to pass it into all of the
663// FakeWindowHandles created throughout the tests.
664// TODO(b/210460522): Update the tests to avoid the need to have the trace be a global variable.
665static std::shared_ptr<VerifyingTrace> gVerifyingTrace = std::make_shared<VerifyingTrace>();
666
Michael Wrightd02c5b62014-02-10 15:10:22 -0800667class InputDispatcherTest : public testing::Test {
668protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000669 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700670 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800671
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000672 void SetUp() override {
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000673 gVerifyingTrace->reset();
Prabir Pradhana41d2442023-04-20 21:30:40 +0000674 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000675 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy,
676 std::make_unique<FakeInputTracingBackend>(
677 gVerifyingTrace));
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700678
Harry Cutts101ee9b2023-07-06 18:04:14 +0000679 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000680 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700681 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800682 }
683
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000684 void TearDown() override {
Prabir Pradhan0eaf1402024-02-05 22:43:04 +0000685 ASSERT_NO_FATAL_FAILURE(gVerifyingTrace->verifyExpectedEventsTraced());
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700686 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000687 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700688 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800689 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700690
691 /**
692 * Used for debugging when writing the test
693 */
694 void dumpDispatcherState() {
695 std::string dump;
696 mDispatcher->dump(dump);
697 std::stringstream ss(dump);
698 std::string to;
699
700 while (std::getline(ss, to, '\n')) {
701 ALOGE("%s", to.c_str());
702 }
703 }
Vishnu Nair958da932020-08-21 17:12:37 -0700704
Chavi Weingarten847e8512023-03-29 00:26:09 +0000705 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700706 FocusRequest request;
707 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000708 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700709 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
710 request.displayId = window->getInfo()->displayId;
711 mDispatcher->setFocusedWindow(request);
712 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800713};
714
Michael Wrightd02c5b62014-02-10 15:10:22 -0800715TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
716 KeyEvent event;
717
718 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800719 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
720 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000721 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600722 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800723 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000724 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000725 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800726 << "Should reject key events with undefined action.";
727
728 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800729 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
730 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600731 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800732 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000733 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000734 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800735 << "Should reject key events with ACTION_MULTIPLE.";
736}
737
738TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
739 MotionEvent event;
740 PointerProperties pointerProperties[MAX_POINTERS + 1];
741 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800742 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800743 pointerProperties[i].clear();
744 pointerProperties[i].id = i;
745 pointerCoords[i].clear();
746 }
747
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800748 // Some constants commonly used below
749 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
750 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
751 constexpr int32_t metaState = AMETA_NONE;
752 constexpr MotionClassification classification = MotionClassification::NONE;
753
chaviw9eaa22c2020-07-01 16:21:27 -0700754 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800755 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800756 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000757 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700758 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700759 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
760 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000761 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800762 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000763 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000764 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800765 << "Should reject motion events with undefined action.";
766
767 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800768 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800769 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
770 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
771 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
772 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000773 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800774 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000775 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000776 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800777 << "Should reject motion events with pointer down index too large.";
778
Garfield Tanfbe732e2020-01-24 11:26:14 -0800779 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700780 AMOTION_EVENT_ACTION_POINTER_DOWN |
781 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700782 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
783 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700784 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000785 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800786 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000787 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000788 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800789 << "Should reject motion events with pointer down index too small.";
790
791 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800792 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800793 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
794 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
795 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
796 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000797 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800798 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000799 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000800 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800801 << "Should reject motion events with pointer up index too large.";
802
Garfield Tanfbe732e2020-01-24 11:26:14 -0800803 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700804 AMOTION_EVENT_ACTION_POINTER_UP |
805 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700806 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
807 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700808 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000809 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800810 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000811 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000812 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800813 << "Should reject motion events with pointer up index too small.";
814
815 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800816 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
817 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700818 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700819 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
820 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000821 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800822 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000823 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000824 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800825 << "Should reject motion events with 0 pointers.";
826
Garfield Tanfbe732e2020-01-24 11:26:14 -0800827 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
828 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700829 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700830 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
831 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000832 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800833 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000834 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000835 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800836 << "Should reject motion events with more than MAX_POINTERS pointers.";
837
838 // Rejects motion events with invalid pointer ids.
839 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800840 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
841 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700842 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700843 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
844 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000845 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800846 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000847 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000848 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800849 << "Should reject motion events with pointer ids less than 0.";
850
851 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800852 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
853 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700854 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700855 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
856 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000857 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800858 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000859 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000860 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800861 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
862
863 // Rejects motion events with duplicate pointer ids.
864 pointerProperties[0].id = 1;
865 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800866 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
867 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700868 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700869 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
870 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000871 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800872 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000873 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000874 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800875 << "Should reject motion events with duplicate pointer ids.";
876}
877
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800878/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
879
880TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
881 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000882 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800883 ASSERT_TRUE(mDispatcher->waitForIdle());
884
885 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
886}
887
888TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000889 NotifySwitchArgs args(InputEvent::nextId(), /*eventTime=*/20, /*policyFlags=*/0,
890 /*switchValues=*/1,
Harry Cutts33476232023-01-30 19:57:29 +0000891 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000892 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800893
894 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
895 args.policyFlags |= POLICY_FLAG_TRUSTED;
896 mFakePolicy->assertNotifySwitchWasCalled(args);
897}
898
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700899namespace {
900
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700901static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700902// Default input dispatching timeout if there is no focused application or paused window
903// from which to determine an appropriate dispatching timeout.
904static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
905 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
906 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800907
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800908class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800909public:
Garfield Tan15601662020-09-22 15:32:38 -0700910 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700911 : mConsumer(std::move(clientChannel)), mName(name) {}
chaviwd1c23182019-12-20 18:44:56 -0800912
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800913 std::unique_ptr<InputEvent> consume(std::chrono::milliseconds timeout, bool handled = false) {
914 auto [consumeSeq, event] = receiveEvent(timeout);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700915 if (!consumeSeq) {
916 return nullptr;
917 }
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000918 finishEvent(*consumeSeq, handled);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800919 return std::move(event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700920 }
921
922 /**
923 * Receive an event without acknowledging it.
924 * Return the sequence number that could later be used to send finished signal.
925 */
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800926 std::pair<std::optional<uint32_t>, std::unique_ptr<InputEvent>> receiveEvent(
927 std::chrono::milliseconds timeout) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800928 uint32_t consumeSeq;
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800929 std::unique_ptr<InputEvent> event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800930
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800931 std::chrono::time_point start = std::chrono::steady_clock::now();
932 status_t status = WOULD_BLOCK;
933 while (status == WOULD_BLOCK) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800934 InputEvent* rawEventPtr = nullptr;
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700935 status = mConsumer.consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800936 &rawEventPtr);
937 event = std::unique_ptr<InputEvent>(rawEventPtr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800938 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700939 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800940 break;
941 }
942 }
943
944 if (status == WOULD_BLOCK) {
945 // Just means there's no event available.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800946 return std::make_pair(std::nullopt, nullptr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800947 }
948
949 if (status != OK) {
950 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800951 return std::make_pair(std::nullopt, nullptr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800952 }
953 if (event == nullptr) {
954 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800955 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800956 return std::make_pair(consumeSeq, std::move(event));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700957 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800958
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700959 /**
960 * To be used together with "receiveEvent" to complete the consumption of an event.
961 */
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000962 void finishEvent(uint32_t consumeSeq, bool handled = true) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700963 const status_t status = mConsumer.sendFinishedSignal(consumeSeq, handled);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700964 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800965 }
966
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000967 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700968 const status_t status = mConsumer.sendTimeline(inputEventId, timeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000969 ASSERT_EQ(OK, status);
970 }
971
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700972 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000973 std::optional<int32_t> expectedDisplayId,
974 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800975 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800976
977 ASSERT_NE(nullptr, event) << mName.c_str()
978 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800979 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700980 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
981 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800982
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000983 if (expectedDisplayId.has_value()) {
984 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
985 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800986
Tiger Huang8664f8c2018-10-11 19:14:35 +0800987 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700988 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800989 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700990 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000991 if (expectedFlags.has_value()) {
992 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
993 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800994 break;
995 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700996 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800997 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700998 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000999 if (expectedFlags.has_value()) {
1000 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
1001 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001002 break;
1003 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001004 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001005 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
1006 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001007 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -08001008 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
1009 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001010 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001011 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
1012 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001013 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +08001014 FAIL() << "Use 'consumeDragEvent' for DRAG events";
1015 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001016 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001017 }
1018
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001019 std::unique_ptr<MotionEvent> consumeMotion() {
1020 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001021
1022 if (event == nullptr) {
1023 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
1024 return nullptr;
1025 }
1026
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001027 if (event->getType() != InputEventType::MOTION) {
1028 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001029 return nullptr;
1030 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001031 return std::unique_ptr<MotionEvent>(static_cast<MotionEvent*>(event.release()));
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001032 }
1033
1034 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001035 std::unique_ptr<MotionEvent> motionEvent = consumeMotion();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001036 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1037 ASSERT_THAT(*motionEvent, matcher);
1038 }
1039
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001040 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001041 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001042 ASSERT_NE(nullptr, event) << mName.c_str()
1043 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001044 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1045 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001046
1047 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1048 << mName.c_str() << ": event displayId should always be NONE.";
1049
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001050 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1051 EXPECT_EQ(hasFocus, focusEvent.getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001052 }
1053
Prabir Pradhan99987712020-11-10 18:43:05 -08001054 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001055 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -08001056 ASSERT_NE(nullptr, event) << mName.c_str()
1057 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001058 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1059 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001060
1061 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1062 << mName.c_str() << ": event displayId should always be NONE.";
1063
1064 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1065 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1066 }
1067
arthurhungb89ccb02020-12-30 16:19:01 +08001068 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001069 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +08001070 ASSERT_NE(nullptr, event) << mName.c_str()
1071 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001072 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001073
1074 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1075 << mName.c_str() << ": event displayId should always be NONE.";
1076
1077 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1078 EXPECT_EQ(isExiting, dragEvent.isExiting());
1079 EXPECT_EQ(x, dragEvent.getX());
1080 EXPECT_EQ(y, dragEvent.getY());
1081 }
1082
Antonio Kantekf16f2832021-09-28 04:39:20 +00001083 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001084 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +00001085 ASSERT_NE(nullptr, event) << mName.c_str()
1086 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001087 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1088 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001089
1090 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1091 << mName.c_str() << ": event displayId should always be NONE.";
1092 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1093 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1094 }
1095
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001096 void assertNoEvents(std::chrono::milliseconds timeout) {
1097 std::unique_ptr<InputEvent> event = consume(timeout);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001098 if (event == nullptr) {
1099 return;
1100 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001101 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001102 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001103 ADD_FAILURE() << "Received key event " << keyEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001104 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001105 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001106 ADD_FAILURE() << "Received motion event " << motionEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001107 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001108 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1109 ADD_FAILURE() << "Received focus event, hasFocus = "
1110 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001111 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001112 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1113 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1114 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001115 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001116 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1117 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1118 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001119 }
1120 FAIL() << mName.c_str()
1121 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001122 }
1123
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001124 sp<IBinder> getToken() { return mConsumer.getChannel()->getConnectionToken(); }
chaviwd1c23182019-12-20 18:44:56 -08001125
Siarhei Vishniakou8d660132024-01-11 16:48:44 -08001126 int getChannelFd() { return mConsumer.getChannel()->getFd(); }
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001127
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001128private:
1129 InputConsumer mConsumer;
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001130 DynamicInputEventFactory mEventFactory;
chaviwd1c23182019-12-20 18:44:56 -08001131
1132 std::string mName;
1133};
1134
chaviw3277faf2021-05-19 16:45:23 -05001135class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001136public:
1137 static const int32_t WIDTH = 600;
1138 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001139
Chris Yea209fde2020-07-22 13:54:51 -07001140 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001141 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001142 int32_t displayId, bool createInputChannel = true)
chaviwd1c23182019-12-20 18:44:56 -08001143 : mName(name) {
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001144 sp<IBinder> token;
1145 if (createInputChannel) {
Garfield Tan15601662020-09-22 15:32:38 -07001146 base::Result<std::unique_ptr<InputChannel>> channel =
1147 dispatcher->createInputChannel(name);
1148 token = (*channel)->getConnectionToken();
1149 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001150 }
1151
1152 inputApplicationHandle->updateInfo();
1153 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1154
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001155 mInfo.token = token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001156 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001157 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001158 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001159 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001160 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001161 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001162 mInfo.globalScaleFactor = 1.0;
1163 mInfo.touchableRegion.clear();
1164 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001165 mInfo.ownerPid = WINDOW_PID;
1166 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001167 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001168 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001169 }
1170
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001171 sp<FakeWindowHandle> clone(int32_t displayId) {
1172 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1173 handle->mInfo = mInfo;
1174 handle->mInfo.displayId = displayId;
1175 handle->mInfo.id = sId++;
1176 handle->mInputReceiver = mInputReceiver;
1177 return handle;
1178 }
1179
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001180 void setTouchable(bool touchable) {
1181 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1182 }
chaviwd1c23182019-12-20 18:44:56 -08001183
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001184 void setFocusable(bool focusable) {
1185 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1186 }
1187
1188 void setVisible(bool visible) {
1189 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1190 }
Vishnu Nair958da932020-08-21 17:12:37 -07001191
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001192 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001193 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001194 }
1195
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001196 void setPaused(bool paused) {
1197 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1198 }
1199
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001200 void setPreventSplitting(bool preventSplitting) {
1201 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001202 }
1203
1204 void setSlippery(bool slippery) {
1205 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1206 }
1207
1208 void setWatchOutsideTouch(bool watchOutside) {
1209 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1210 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001211
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001212 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1213
1214 void setInterceptsStylus(bool interceptsStylus) {
1215 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1216 }
1217
1218 void setDropInput(bool dropInput) {
1219 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1220 }
1221
1222 void setDropInputIfObscured(bool dropInputIfObscured) {
1223 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1224 }
1225
1226 void setNoInputChannel(bool noInputChannel) {
1227 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1228 }
1229
Josep del Riob3981622023-04-18 15:49:45 +00001230 void setDisableUserActivity(bool disableUserActivity) {
1231 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1232 }
1233
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07001234 void setGlobalStylusBlocksTouch(bool shouldGlobalStylusBlockTouch) {
1235 mInfo.setInputConfig(WindowInfo::InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH,
1236 shouldGlobalStylusBlockTouch);
1237 }
1238
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001239 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1240
chaviw3277faf2021-05-19 16:45:23 -05001241 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001242
Bernardo Rufino7393d172021-02-26 13:56:11 +00001243 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1244
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001245 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001246 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001247 mInfo.touchableRegion.clear();
1248 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001249
1250 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1251 ui::Transform translate;
1252 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1253 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001254 }
1255
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001256 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1257
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001258 void setIsWallpaper(bool isWallpaper) {
1259 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1260 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001261
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001262 void setDupTouchToWallpaper(bool hasWallpaper) {
1263 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1264 }
chaviwd1c23182019-12-20 18:44:56 -08001265
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001266 void setTrustedOverlay(bool trustedOverlay) {
1267 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1268 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001269
chaviw9eaa22c2020-07-01 16:21:27 -07001270 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1271 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1272 }
1273
1274 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001275
yunho.shinf4a80b82020-11-16 21:13:57 +09001276 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1277
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001278 std::unique_ptr<KeyEvent> consumeKey(bool handled = true) {
1279 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED, handled);
1280 if (event == nullptr) {
1281 ADD_FAILURE() << "No event";
1282 return nullptr;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001283 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001284 if (event->getType() != InputEventType::KEY) {
1285 ADD_FAILURE() << "Instead of key event, got " << event;
1286 return nullptr;
1287 }
1288 return std::unique_ptr<KeyEvent>(static_cast<KeyEvent*>(event.release()));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001289 }
1290
1291 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001292 std::unique_ptr<KeyEvent> keyEvent = consumeKey();
1293 ASSERT_NE(nullptr, keyEvent);
1294 ASSERT_THAT(*keyEvent, matcher);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001295 }
1296
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001297 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001298 consumeKeyEvent(AllOf(WithKeyAction(ACTION_DOWN), WithDisplayId(expectedDisplayId),
1299 WithFlags(expectedFlags)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001300 }
1301
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001302 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001303 consumeKeyEvent(AllOf(WithKeyAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1304 WithFlags(expectedFlags)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001305 }
1306
Svet Ganov5d3bc372020-01-26 23:11:07 -08001307 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001308 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001309 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1310 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001311 }
1312
1313 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001314 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001315 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1316 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001317 }
1318
1319 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001320 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001321 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1322 }
1323
1324 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1325 std::optional<int32_t> expectedFlags = std::nullopt) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001326 consumeMotionEvent(
1327 AllOf(WithMotionAction(ACTION_DOWN),
1328 testing::Conditional(expectedDisplayId.has_value(),
1329 WithDisplayId(*expectedDisplayId), testing::_),
1330 testing::Conditional(expectedFlags.has_value(), WithFlags(*expectedFlags),
1331 testing::_)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001332 }
1333
Svet Ganov5d3bc372020-01-26 23:11:07 -08001334 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001335 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1336 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001337 const int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001338 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001339 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1340 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001341 }
1342
1343 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001344 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001345 const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001346 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001347 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1348 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001349 }
1350
1351 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001352 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001353 consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1354 WithFlags(expectedFlags)));
Michael Wright3a240c42019-12-10 20:53:41 +00001355 }
1356
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001357 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1358 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001359 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE),
1360 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001361 }
1362
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001363 void consumeMotionOutsideWithZeroedCoords() {
1364 consumeMotionEvent(
1365 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE), WithRawCoords(0, 0)));
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001366 }
1367
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001368 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1369 ASSERT_NE(mInputReceiver, nullptr)
1370 << "Cannot consume events from a window with no receiver";
1371 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1372 }
1373
Prabir Pradhan99987712020-11-10 18:43:05 -08001374 void consumeCaptureEvent(bool hasCapture) {
1375 ASSERT_NE(mInputReceiver, nullptr)
1376 << "Cannot consume events from a window with no receiver";
1377 mInputReceiver->consumeCaptureEvent(hasCapture);
1378 }
1379
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001380 std::unique_ptr<MotionEvent> consumeMotionEvent(
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001381 const ::testing::Matcher<MotionEvent>& matcher = testing::_) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001382 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
1383 if (event == nullptr) {
1384 ADD_FAILURE() << "No event";
1385 return nullptr;
Prabir Pradhan5893d362023-11-17 04:30:40 +00001386 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001387 if (event->getType() != InputEventType::MOTION) {
1388 ADD_FAILURE() << "Instead of motion event, got " << *event;
1389 return nullptr;
1390 }
1391 std::unique_ptr<MotionEvent> motionEvent =
1392 std::unique_ptr<MotionEvent>(static_cast<MotionEvent*>(event.release()));
1393 EXPECT_THAT(*motionEvent, matcher);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001394 return motionEvent;
chaviwd1c23182019-12-20 18:44:56 -08001395 }
1396
arthurhungb89ccb02020-12-30 16:19:01 +08001397 void consumeDragEvent(bool isExiting, float x, float y) {
1398 mInputReceiver->consumeDragEvent(isExiting, x, y);
1399 }
1400
Antonio Kantekf16f2832021-09-28 04:39:20 +00001401 void consumeTouchModeEvent(bool inTouchMode) {
1402 ASSERT_NE(mInputReceiver, nullptr)
1403 << "Cannot consume events from a window with no receiver";
1404 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1405 }
1406
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001407 std::pair<std::optional<uint32_t>, std::unique_ptr<InputEvent>> receiveEvent() {
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001408 return receive();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001409 }
1410
1411 void finishEvent(uint32_t sequenceNum) {
1412 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1413 mInputReceiver->finishEvent(sequenceNum);
1414 }
1415
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001416 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1417 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1418 mInputReceiver->sendTimeline(inputEventId, timeline);
1419 }
1420
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001421 void assertNoEvents(std::chrono::milliseconds timeout = CONSUME_TIMEOUT_NO_EVENT_EXPECTED) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001422 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001423 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001424 return; // Can't receive events if the window does not have input channel
1425 }
1426 ASSERT_NE(nullptr, mInputReceiver)
1427 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001428 mInputReceiver->assertNoEvents(timeout);
Arthur Hungb92218b2018-08-14 12:00:21 +08001429 }
1430
chaviwaf87b3e2019-10-01 16:59:28 -07001431 sp<IBinder> getToken() { return mInfo.token; }
1432
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001433 const std::string& getName() { return mName; }
1434
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001435 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001436 mInfo.ownerPid = ownerPid;
1437 mInfo.ownerUid = ownerUid;
1438 }
1439
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001440 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001441
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001442 void destroyReceiver() { mInputReceiver = nullptr; }
1443
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001444 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1445
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001446 // FakeWindowHandle uses this consume method to ensure received events are added to the trace.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001447 std::unique_ptr<InputEvent> consume(std::chrono::milliseconds timeout, bool handled = true) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001448 if (mInputReceiver == nullptr) {
1449 LOG(FATAL) << "Cannot consume event from a window with no input event receiver";
1450 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001451 std::unique_ptr<InputEvent> event = mInputReceiver->consume(timeout, handled);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001452 if (event == nullptr) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001453 ADD_FAILURE() << "Consume failed: no event";
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001454 }
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001455 expectReceivedEventTraced(event);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001456 return event;
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001457 }
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001458
1459private:
1460 FakeWindowHandle(std::string name) : mName(name){};
1461 const std::string mName;
1462 std::shared_ptr<FakeInputReceiver> mInputReceiver;
1463 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
1464 friend class sp<FakeWindowHandle>;
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001465
1466 // FakeWindowHandle uses this receive method to ensure received events are added to the trace.
1467 std::pair<std::optional<uint32_t /*seq*/>, std::unique_ptr<InputEvent>> receive() {
1468 if (mInputReceiver == nullptr) {
1469 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1470 return std::make_pair(std::nullopt, nullptr);
1471 }
1472 auto out = mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1473 const auto& [_, event] = out;
1474 expectReceivedEventTraced(event);
1475 return std::move(out);
1476 }
1477
1478 void expectReceivedEventTraced(const std::unique_ptr<InputEvent>& event) {
1479 if (!event) {
1480 return;
1481 }
1482
1483 switch (event->getType()) {
1484 case InputEventType::KEY: {
1485 gVerifyingTrace->expectKeyDispatchTraced(static_cast<KeyEvent&>(*event));
1486 break;
1487 }
1488 case InputEventType::MOTION: {
1489 gVerifyingTrace->expectMotionDispatchTraced(static_cast<MotionEvent&>(*event));
1490 break;
1491 }
1492 default:
1493 break;
1494 }
1495 }
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001496};
1497
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001498std::atomic<int32_t> FakeWindowHandle::sId{1};
1499
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001500class FakeMonitorReceiver {
1501public:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001502 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId)
1503 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001504
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001505 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001506
1507 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001508 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1509 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001510 }
1511
1512 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001513 const auto [sequenceNum, _] = mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1514 return sequenceNum;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001515 }
1516
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001517 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001518
1519 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001520 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1521 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001522 }
1523
1524 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001525 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1526 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001527 }
1528
1529 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001530 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1531 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001532 }
1533
1534 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001535 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001536 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1537 WithDisplayId(expectedDisplayId),
1538 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1539 }
1540
1541 void consumeMotionPointerDown(int32_t pointerIdx) {
1542 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1543 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001544 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1545 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001546 }
1547
1548 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001549 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001550 }
1551
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001552 std::unique_ptr<MotionEvent> consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001553
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001554 void assertNoEvents() { mInputReceiver.assertNoEvents(CONSUME_TIMEOUT_NO_EVENT_EXPECTED); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001555
1556private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001557 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001558};
1559
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001560static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001561 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001562 int32_t displayId = ADISPLAY_ID_NONE,
1563 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001564 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001565 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001566 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001567 KeyEvent event;
1568 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1569
1570 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001571 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001572 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1573 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001574
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001575 if (!allowKeyRepeat) {
1576 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1577 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001578 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001579 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001580}
1581
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001582static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1583 InputEventInjectionResult result =
1584 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1585 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1586 if (result != InputEventInjectionResult::TIMED_OUT) {
1587 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1588 }
1589}
1590
1591static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001592 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001593 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001594}
1595
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001596// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1597// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1598// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001599static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1600 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001601 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001602 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001603 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001604}
1605
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001606static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001607 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001608 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001609}
1610
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001611static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001612 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001613 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001614 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001615 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001616 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1617 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001618}
1619
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001620static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001621 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1622 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001623 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001624 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1625 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001626 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001627 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001628 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001629 MotionEventBuilder motionBuilder =
1630 MotionEventBuilder(action, source)
1631 .displayId(displayId)
1632 .eventTime(eventTime)
1633 .rawXCursorPosition(cursorPosition.x)
1634 .rawYCursorPosition(cursorPosition.y)
1635 .pointer(
1636 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1637 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1638 motionBuilder.downTime(eventTime);
1639 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001640
1641 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001642 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1643 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001644}
1645
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001646static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1647 int32_t displayId,
1648 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001649 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001650}
1651
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001652static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1653 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001654 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001655 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001656}
1657
Jackal Guof9696682018-10-05 12:23:23 +08001658static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1659 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1660 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001661 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1662 AINPUT_SOURCE_KEYBOARD, displayId, POLICY_FLAG_PASS_TO_USER, action,
1663 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001664
1665 return args;
1666}
1667
Josep del Riob3981622023-04-18 15:49:45 +00001668static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1669 int32_t displayId = ADISPLAY_ID_NONE) {
1670 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1671 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001672 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1673 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C,
1674 AMETA_META_ON, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001675
1676 return args;
1677}
1678
1679static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1680 int32_t displayId = ADISPLAY_ID_NONE) {
1681 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1682 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001683 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1684 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST,
1685 KEY_ASSISTANT, AMETA_NONE, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001686
1687 return args;
1688}
1689
Prabir Pradhan678438e2023-04-13 19:32:51 +00001690[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1691 int32_t displayId,
1692 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001693 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001694 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1695 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1696 }
1697
chaviwd1c23182019-12-20 18:44:56 -08001698 PointerProperties pointerProperties[pointerCount];
1699 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001700
chaviwd1c23182019-12-20 18:44:56 -08001701 for (size_t i = 0; i < pointerCount; i++) {
1702 pointerProperties[i].clear();
1703 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001704 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001705
chaviwd1c23182019-12-20 18:44:56 -08001706 pointerCoords[i].clear();
1707 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1708 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1709 }
Jackal Guof9696682018-10-05 12:23:23 +08001710
1711 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1712 // Define a valid motion event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001713 NotifyMotionArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, source,
1714 displayId, POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0,
1715 /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001716 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001717 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001718 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001719 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001720
1721 return args;
1722}
1723
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001724static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1725 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1726}
1727
chaviwd1c23182019-12-20 18:44:56 -08001728static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1729 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1730}
1731
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001732static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1733 const PointerCaptureRequest& request) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001734 return NotifyPointerCaptureChangedArgs(InputEvent::nextId(), systemTime(SYSTEM_TIME_MONOTONIC),
1735 request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001736}
1737
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001738} // namespace
1739
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001740/**
1741 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1742 * broken channel.
1743 */
1744TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1745 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1746 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001747 sp<FakeWindowHandle>::make(application, mDispatcher,
1748 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001749
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001750 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001751
1752 // Window closes its channel, but the window remains.
1753 window->destroyReceiver();
1754 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1755}
1756
Arthur Hungb92218b2018-08-14 12:00:21 +08001757TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001758 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001759 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1760 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001761
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001762 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001763 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001764 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001765 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001766
1767 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001768 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001769}
1770
Siarhei Vishniakouaeed0da2024-01-09 08:57:13 -08001771using InputDispatcherDeathTest = InputDispatcherTest;
1772
1773/**
1774 * When 'onWindowInfosChanged' arguments contain a duplicate entry for the same window, dispatcher
1775 * should crash.
1776 */
1777TEST_F(InputDispatcherDeathTest, DuplicateWindowInfosAbortDispatcher) {
1778 testing::GTEST_FLAG(death_test_style) = "threadsafe";
1779 ScopedSilentDeath _silentDeath;
1780
1781 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1782 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1783 "Fake Window", ADISPLAY_ID_DEFAULT);
1784 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
1785 {{*window->getInfo(), *window->getInfo()}, {}, 0, 0}),
1786 "Incorrect WindowInfosUpdate provided");
1787}
1788
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001789TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1790 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001791 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1792 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001793
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001794 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001795 // Inject a MotionEvent to an unknown display.
1796 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001797 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001798 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1799
1800 // Window should receive motion event.
1801 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1802}
1803
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001804/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001805 * Calling onWindowInfosChanged once should not cause any issues.
1806 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001807 * called twice.
1808 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001809TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001810 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001811 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1812 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001813 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001814
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001815 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001816 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001817 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001818 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001819 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001820
1821 // Window should receive motion event.
1822 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1823}
1824
1825/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001826 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001827 */
1828TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001829 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001830 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1831 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001832 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001833
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001834 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1835 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001836 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001837 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001838 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001839 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001840
1841 // Window should receive motion event.
1842 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1843}
1844
Arthur Hungb92218b2018-08-14 12:00:21 +08001845// The foreground window should receive the first touch down event.
1846TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001847 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001848 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001849 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001850 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001851 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001852
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001853 mDispatcher->onWindowInfosChanged(
1854 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001855 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001856 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001857 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001858
1859 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001860 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001861 windowSecond->assertNoEvents();
1862}
1863
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001864/**
1865 * Two windows: A top window, and a wallpaper behind the window.
1866 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1867 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001868 * 1. foregroundWindow <-- dup touch to wallpaper
1869 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001870 */
1871TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1872 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1873 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001874 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001875 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001876 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001877 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001878 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001879
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001880 mDispatcher->onWindowInfosChanged(
1881 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001882 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001883 injectMotionEvent(*mDispatcher,
1884 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1885 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
1886 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001887 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1888
1889 // Both foreground window and its wallpaper should receive the touch down
1890 foregroundWindow->consumeMotionDown();
1891 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1892
1893 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001894 injectMotionEvent(*mDispatcher,
1895 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1896 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
1897 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001898 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1899
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001900 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001901 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1902
1903 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001904 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001905 foregroundWindow->consumeMotionCancel();
1906 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1907 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1908}
1909
1910/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001911 * Two fingers down on the window, and lift off the first finger.
1912 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1913 * contains a single pointer.
1914 */
1915TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1916 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1917 sp<FakeWindowHandle> window =
1918 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1919
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001920 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001921 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001922 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1923 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1924 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001925 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001926 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1927 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1928 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1929 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001930 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001931 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1932 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1933 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1934 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001935 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1936 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1937 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1938
1939 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001940 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001941 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1942 window->consumeMotionEvent(
1943 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1944}
1945
1946/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001947 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1948 * with the following differences:
1949 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1950 * clean up the connection.
1951 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1952 * Ensure that there's no crash in the dispatcher.
1953 */
1954TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1955 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1956 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001957 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001958 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001959 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001960 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001961 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001962
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001963 mDispatcher->onWindowInfosChanged(
1964 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001965 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001966 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001967 {100, 200}))
1968 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1969
1970 // Both foreground window and its wallpaper should receive the touch down
1971 foregroundWindow->consumeMotionDown();
1972 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1973
1974 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001975 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001976 ADISPLAY_ID_DEFAULT, {110, 200}))
1977 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1978
1979 foregroundWindow->consumeMotionMove();
1980 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1981
1982 // Wallpaper closes its channel, but the window remains.
1983 wallpaperWindow->destroyReceiver();
1984 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1985
1986 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1987 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001988 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001989 foregroundWindow->consumeMotionCancel();
1990}
1991
Arthur Hungc539dbb2022-12-08 07:45:36 +00001992class ShouldSplitTouchFixture : public InputDispatcherTest,
1993 public ::testing::WithParamInterface<bool> {};
1994INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1995 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001996/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001997 * A single window that receives touch (on top), and a wallpaper window underneath it.
1998 * The top window gets a multitouch gesture.
1999 * Ensure that wallpaper gets the same gesture.
2000 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00002001TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002002 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002003 sp<FakeWindowHandle> foregroundWindow =
2004 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
2005 foregroundWindow->setDupTouchToWallpaper(true);
2006 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002007
2008 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002009 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002010 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002011
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002012 mDispatcher->onWindowInfosChanged(
2013 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002014
2015 // Touch down on top window
2016 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002017 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002018 {100, 100}))
2019 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2020
2021 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00002022 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002023 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2024
2025 // Second finger down on the top window
2026 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002027 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002028 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002029 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2030 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002031 .build();
2032 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002033 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002034 InputEventInjectionSync::WAIT_FOR_RESULT))
2035 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2036
Harry Cutts33476232023-01-30 19:57:29 +00002037 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
2038 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002039 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00002040
2041 const MotionEvent secondFingerUpEvent =
2042 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2043 .displayId(ADISPLAY_ID_DEFAULT)
2044 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002045 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2046 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002047 .build();
2048 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002049 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002050 InputEventInjectionSync::WAIT_FOR_RESULT))
2051 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2052 foregroundWindow->consumeMotionPointerUp(0);
2053 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2054
2055 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002056 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002057 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2058 AINPUT_SOURCE_TOUCHSCREEN)
2059 .displayId(ADISPLAY_ID_DEFAULT)
2060 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00002061 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002062 .x(100)
2063 .y(100))
2064 .build(),
2065 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002066 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2067 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2068 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002069}
2070
2071/**
2072 * Two windows: a window on the left and window on the right.
2073 * A third window, wallpaper, is behind both windows, and spans both top windows.
2074 * The first touch down goes to the left window. A second pointer touches down on the right window.
2075 * The touch is split, so both left and right windows should receive ACTION_DOWN.
2076 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
2077 * ACTION_POINTER_DOWN(1).
2078 */
2079TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
2080 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2081 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002082 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002083 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002084 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002085
2086 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002087 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002088 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002089 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002090
2091 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002092 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002093 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002094 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002095
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002096 mDispatcher->onWindowInfosChanged(
2097 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2098 {},
2099 0,
2100 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002101
2102 // Touch down on left window
2103 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002104 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002105 {100, 100}))
2106 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2107
2108 // Both foreground window and its wallpaper should receive the touch down
2109 leftWindow->consumeMotionDown();
2110 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2111
2112 // Second finger down on the right window
2113 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002114 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002115 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002116 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2117 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002118 .build();
2119 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002120 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002121 InputEventInjectionSync::WAIT_FOR_RESULT))
2122 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2123
2124 leftWindow->consumeMotionMove();
2125 // Since the touch is split, right window gets ACTION_DOWN
2126 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002127 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002128 expectedWallpaperFlags);
2129
2130 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002131 mDispatcher->onWindowInfosChanged(
2132 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002133 leftWindow->consumeMotionCancel();
2134 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2135 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2136
2137 // The pointer that's still down on the right window moves, and goes to the right window only.
2138 // As far as the dispatcher's concerned though, both pointers are still present.
2139 const MotionEvent secondFingerMoveEvent =
2140 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2141 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002142 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2143 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002144 .build();
2145 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002146 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002147 InputEventInjectionSync::WAIT_FOR_RESULT));
2148 rightWindow->consumeMotionMove();
2149
2150 leftWindow->assertNoEvents();
2151 rightWindow->assertNoEvents();
2152 wallpaperWindow->assertNoEvents();
2153}
2154
Arthur Hungc539dbb2022-12-08 07:45:36 +00002155/**
2156 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2157 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2158 * The right window should receive ACTION_DOWN.
2159 */
2160TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002161 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002162 sp<FakeWindowHandle> leftWindow =
2163 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2164 leftWindow->setFrame(Rect(0, 0, 200, 200));
2165 leftWindow->setDupTouchToWallpaper(true);
2166 leftWindow->setSlippery(true);
2167
2168 sp<FakeWindowHandle> rightWindow =
2169 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2170 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002171
2172 sp<FakeWindowHandle> wallpaperWindow =
2173 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2174 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002175
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002176 mDispatcher->onWindowInfosChanged(
2177 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2178 {},
2179 0,
2180 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002181
Arthur Hungc539dbb2022-12-08 07:45:36 +00002182 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002183 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002184 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002185 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002186 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002187
2188 // Both foreground window and its wallpaper should receive the touch down
2189 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002190 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2191
Arthur Hungc539dbb2022-12-08 07:45:36 +00002192 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002193 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002194 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002195 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002196 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2197
Arthur Hungc539dbb2022-12-08 07:45:36 +00002198 leftWindow->consumeMotionCancel();
2199 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2200 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002201}
2202
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002203/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002204 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2205 * interactive, it might stop sending this flag.
2206 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2207 * to have a consistent input stream.
2208 *
2209 * Test procedure:
2210 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2211 * DOWN (new gesture).
2212 *
2213 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2214 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2215 *
2216 * We technically just need a single window here, but we are using two windows (spy on top and a
2217 * regular window below) to emulate the actual situation where it happens on the device.
2218 */
2219TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2220 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2221 sp<FakeWindowHandle> spyWindow =
2222 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2223 spyWindow->setFrame(Rect(0, 0, 200, 200));
2224 spyWindow->setTrustedOverlay(true);
2225 spyWindow->setSpy(true);
2226
2227 sp<FakeWindowHandle> window =
2228 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2229 window->setFrame(Rect(0, 0, 200, 200));
2230
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002231 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002232 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002233
2234 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002235 mDispatcher->notifyMotion(
2236 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2237 .deviceId(touchDeviceId)
2238 .policyFlags(DEFAULT_POLICY_FLAGS)
2239 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2240 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002241
Prabir Pradhan678438e2023-04-13 19:32:51 +00002242 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2243 .deviceId(touchDeviceId)
2244 .policyFlags(DEFAULT_POLICY_FLAGS)
2245 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2246 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2247 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002248 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2249 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2250 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2251 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2252
2253 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002254 mDispatcher->notifyMotion(
2255 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2256 .deviceId(touchDeviceId)
2257 .policyFlags(0)
2258 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2259 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2260 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002261 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2262 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2263
2264 // We don't need to reset the device to reproduce the issue, but the reset event typically
2265 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002266 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002267
2268 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002269 mDispatcher->notifyMotion(
2270 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2271 .deviceId(touchDeviceId)
2272 .policyFlags(DEFAULT_POLICY_FLAGS)
2273 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2274 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002275 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2276 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2277
2278 // No more events
2279 spyWindow->assertNoEvents();
2280 window->assertNoEvents();
2281}
2282
2283/**
Linnan Li907ae732023-09-05 17:14:21 +08002284 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
2285 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2286 * interactive, it might stop sending this flag.
2287 * We've already ensured the consistency of the touch event in this case, and we should also ensure
2288 * the consistency of the hover event in this case.
2289 *
2290 * Test procedure:
2291 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
2292 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
2293 *
2294 * We expect to receive two full streams of hover events.
2295 */
2296TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
2297 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2298
2299 sp<FakeWindowHandle> window =
2300 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2301 window->setFrame(Rect(0, 0, 300, 300));
2302
2303 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2304
2305 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2306 .policyFlags(DEFAULT_POLICY_FLAGS)
2307 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2308 .build());
2309 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2310
2311 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2312 .policyFlags(DEFAULT_POLICY_FLAGS)
2313 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2314 .build());
2315 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2316
2317 // Send hover exit without the default policy flags.
2318 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2319 .policyFlags(0)
2320 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2321 .build());
2322
2323 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2324
2325 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
2326 // right event.
2327 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2328 .policyFlags(DEFAULT_POLICY_FLAGS)
2329 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
2330 .build());
2331 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2332
2333 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2334 .policyFlags(DEFAULT_POLICY_FLAGS)
2335 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2336 .build());
2337 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2338
2339 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2340 .policyFlags(DEFAULT_POLICY_FLAGS)
2341 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2342 .build());
2343 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2344}
2345
2346/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002347 * Two windows: a window on the left and a window on the right.
2348 * Mouse is hovered from the right window into the left window.
2349 * Next, we tap on the left window, where the cursor was last seen.
2350 * The second tap is done onto the right window.
2351 * The mouse and tap are from two different devices.
2352 * We technically don't need to set the downtime / eventtime for these events, but setting these
2353 * explicitly helps during debugging.
2354 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2355 * In the buggy implementation, a tap on the right window would cause a crash.
2356 */
2357TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2358 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2359 sp<FakeWindowHandle> leftWindow =
2360 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2361 leftWindow->setFrame(Rect(0, 0, 200, 200));
2362
2363 sp<FakeWindowHandle> rightWindow =
2364 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2365 rightWindow->setFrame(Rect(200, 0, 400, 200));
2366
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002367 mDispatcher->onWindowInfosChanged(
2368 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002369 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2370 // stale.
2371 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2372 const int32_t mouseDeviceId = 6;
2373 const int32_t touchDeviceId = 4;
2374 // Move the cursor from right
2375 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002376 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002377 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2378 AINPUT_SOURCE_MOUSE)
2379 .deviceId(mouseDeviceId)
2380 .downTime(baseTime + 10)
2381 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002382 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002383 .build()));
2384 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2385
2386 // .. to the left window
2387 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002388 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002389 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2390 AINPUT_SOURCE_MOUSE)
2391 .deviceId(mouseDeviceId)
2392 .downTime(baseTime + 10)
2393 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002394 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002395 .build()));
2396 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2397 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2398 // Now tap the left window
2399 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002400 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002401 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2402 AINPUT_SOURCE_TOUCHSCREEN)
2403 .deviceId(touchDeviceId)
2404 .downTime(baseTime + 40)
2405 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002406 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002407 .build()));
2408 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2409 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2410
2411 // release tap
2412 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002413 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002414 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2415 AINPUT_SOURCE_TOUCHSCREEN)
2416 .deviceId(touchDeviceId)
2417 .downTime(baseTime + 40)
2418 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002419 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002420 .build()));
2421 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2422
2423 // Tap the window on the right
2424 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002425 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002426 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2427 AINPUT_SOURCE_TOUCHSCREEN)
2428 .deviceId(touchDeviceId)
2429 .downTime(baseTime + 60)
2430 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002431 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002432 .build()));
2433 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2434
2435 // release tap
2436 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002437 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002438 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2439 AINPUT_SOURCE_TOUCHSCREEN)
2440 .deviceId(touchDeviceId)
2441 .downTime(baseTime + 60)
2442 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002443 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002444 .build()));
2445 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2446
2447 // No more events
2448 leftWindow->assertNoEvents();
2449 rightWindow->assertNoEvents();
2450}
2451
2452/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002453 * Start hovering in a window. While this hover is still active, make another window appear on top.
2454 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2455 * While the top window is present, the hovering is stopped.
2456 * Later, hovering gets resumed again.
2457 * Ensure that new hover gesture is handled correctly.
2458 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2459 * to the window that's currently being hovered over.
2460 */
2461TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2462 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2463 sp<FakeWindowHandle> window =
2464 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2465 window->setFrame(Rect(0, 0, 200, 200));
2466
2467 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002468 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002469
2470 // Start hovering in the window
2471 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2472 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2473 .build());
2474 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2475
2476 // Now, an obscuring window appears!
2477 sp<FakeWindowHandle> obscuringWindow =
2478 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2479 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002480 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002481 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2482 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2483 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2484 obscuringWindow->setNoInputChannel(true);
2485 obscuringWindow->setFocusable(false);
2486 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002487 mDispatcher->onWindowInfosChanged(
2488 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002489
2490 // While this new obscuring window is present, the hovering is stopped
2491 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2492 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2493 .build());
2494 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2495
2496 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002497 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002498
2499 // And a new hover gesture starts.
2500 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2501 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2502 .build());
2503 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2504}
2505
2506/**
2507 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2508 * the obscuring window.
2509 */
2510TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2511 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2512 sp<FakeWindowHandle> window =
2513 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2514 window->setFrame(Rect(0, 0, 200, 200));
2515
2516 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002517 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002518
2519 // Start hovering in the window
2520 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2521 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2522 .build());
2523 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2524
2525 // Now, an obscuring window appears!
2526 sp<FakeWindowHandle> obscuringWindow =
2527 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2528 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002529 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002530 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2531 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2532 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2533 obscuringWindow->setNoInputChannel(true);
2534 obscuringWindow->setFocusable(false);
2535 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002536 mDispatcher->onWindowInfosChanged(
2537 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002538
2539 // While this new obscuring window is present, the hovering continues. The event can't go to the
2540 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2541 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2542 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2543 .build());
2544 obscuringWindow->assertNoEvents();
2545 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2546
2547 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002548 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002549
2550 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2551 // so it should generate a HOVER_ENTER
2552 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2553 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2554 .build());
2555 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2556
2557 // Now the MOVE should be getting dispatched normally
2558 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2559 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2560 .build());
2561 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2562}
2563
2564/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002565 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2566 * events are delivered to the window.
2567 */
2568TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2569 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2570 sp<FakeWindowHandle> window =
2571 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2572 window->setFrame(Rect(0, 0, 200, 200));
2573 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2574
2575 // Start hovering in the window
2576 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2577 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2578 .build());
2579 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2580
2581 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2582 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2583 .build());
2584 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2585
2586 // Scroll with the mouse
2587 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2588 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2589 .build());
2590 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2591}
2592
2593using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2594
2595/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002596 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2597 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002598 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002599TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002600 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2601 sp<FakeWindowHandle> window =
2602 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2603 window->setFrame(Rect(0, 0, 200, 200));
2604
2605 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2606
2607 constexpr int32_t touchDeviceId = 4;
2608 constexpr int32_t stylusDeviceId = 2;
2609
2610 // Stylus down
2611 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2612 .deviceId(stylusDeviceId)
2613 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2614 .build());
2615 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2616
2617 // Touch down
2618 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2619 .deviceId(touchDeviceId)
2620 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2621 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002622
2623 // Touch move
2624 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2625 .deviceId(touchDeviceId)
2626 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2627 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002628 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002629
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002630 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002631 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2632 .deviceId(stylusDeviceId)
2633 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2634 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002635 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2636 WithCoords(101, 111)));
2637
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002638 window->assertNoEvents();
2639}
2640
2641/**
2642 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002643 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002644 * Similar test as above, but with added SPY window.
2645 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002646TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002647 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2648 sp<FakeWindowHandle> window =
2649 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2650 sp<FakeWindowHandle> spyWindow =
2651 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2652 spyWindow->setFrame(Rect(0, 0, 200, 200));
2653 spyWindow->setTrustedOverlay(true);
2654 spyWindow->setSpy(true);
2655 window->setFrame(Rect(0, 0, 200, 200));
2656
2657 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2658
2659 constexpr int32_t touchDeviceId = 4;
2660 constexpr int32_t stylusDeviceId = 2;
2661
2662 // Stylus down
2663 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2664 .deviceId(stylusDeviceId)
2665 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2666 .build());
2667 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2668 spyWindow->consumeMotionEvent(
2669 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2670
2671 // Touch down
2672 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2673 .deviceId(touchDeviceId)
2674 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2675 .build());
2676
2677 // Touch move
2678 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2679 .deviceId(touchDeviceId)
2680 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2681 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002682
2683 // Touch is ignored because stylus is already down
2684
2685 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002686 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2687 .deviceId(stylusDeviceId)
2688 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2689 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002690 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2691 WithCoords(101, 111)));
2692 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2693 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002694
2695 window->assertNoEvents();
2696 spyWindow->assertNoEvents();
2697}
2698
2699/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002700 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002701 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002702 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002703TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002704 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2705 sp<FakeWindowHandle> window =
2706 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2707 window->setFrame(Rect(0, 0, 200, 200));
2708
2709 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2710
2711 constexpr int32_t touchDeviceId = 4;
2712 constexpr int32_t stylusDeviceId = 2;
2713
2714 // Stylus down on the window
2715 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2716 .deviceId(stylusDeviceId)
2717 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2718 .build());
2719 window->consumeMotionEvent(
2720 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2721
2722 // Touch down on window
2723 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2724 .deviceId(touchDeviceId)
2725 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2726 .build());
2727 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2728 .deviceId(touchDeviceId)
2729 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2730 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002731
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002732 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002733
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002734 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002735 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2736 .deviceId(stylusDeviceId)
2737 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2738 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002739 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2740 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002741
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002742 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002743 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2744 .deviceId(touchDeviceId)
2745 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2746 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002747 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002748}
2749
2750/**
2751 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002752 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002753 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002754TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002755 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2756 sp<FakeWindowHandle> window =
2757 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2758 window->setFrame(Rect(0, 0, 200, 200));
2759
2760 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2761
2762 constexpr int32_t touchDeviceId = 4;
2763 constexpr int32_t stylusDeviceId = 2;
2764
2765 // Touch down on window
2766 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2767 .deviceId(touchDeviceId)
2768 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2769 .build());
2770 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2771 .deviceId(touchDeviceId)
2772 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2773 .build());
2774 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2775 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2776
2777 // Stylus hover on the window
2778 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2779 .deviceId(stylusDeviceId)
2780 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2781 .build());
2782 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2783 .deviceId(stylusDeviceId)
2784 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2785 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002786 // Stylus hover movement causes touch to be canceled
2787 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2788 WithCoords(141, 146)));
2789 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2790 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2791 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2792 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002793
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002794 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002795 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2796 .deviceId(touchDeviceId)
2797 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2798 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002799
2800 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002801}
2802
2803/**
2804 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2805 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2806 * become active.
2807 */
2808TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
2809 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2810 sp<FakeWindowHandle> window =
2811 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2812 window->setFrame(Rect(0, 0, 200, 200));
2813
2814 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2815
2816 constexpr int32_t stylusDeviceId1 = 3;
2817 constexpr int32_t stylusDeviceId2 = 5;
2818
2819 // Touch down on window
2820 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2821 .deviceId(stylusDeviceId1)
2822 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2823 .build());
2824 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2825 .deviceId(stylusDeviceId1)
2826 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2827 .build());
2828 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2829 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2830
2831 // Second stylus down
2832 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2833 .deviceId(stylusDeviceId2)
2834 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2835 .build());
2836 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2837 .deviceId(stylusDeviceId2)
2838 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2839 .build());
2840
2841 // First stylus is canceled, second one takes over.
2842 window->consumeMotionEvent(
2843 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2844 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2845 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2846
2847 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2848 .deviceId(stylusDeviceId1)
2849 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2850 .build());
2851 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002852 window->assertNoEvents();
2853}
2854
2855/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002856 * One window. Touch down on the window. Then, stylus down on the window from another device.
2857 * Ensure that is canceled, because stylus down should be preferred over touch.
2858 */
2859TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
2860 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2861 sp<FakeWindowHandle> window =
2862 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2863 window->setFrame(Rect(0, 0, 200, 200));
2864
2865 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2866
2867 constexpr int32_t touchDeviceId = 4;
2868 constexpr int32_t stylusDeviceId = 2;
2869
2870 // Touch down on window
2871 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2872 .deviceId(touchDeviceId)
2873 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2874 .build());
2875 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2876 .deviceId(touchDeviceId)
2877 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2878 .build());
2879 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2880 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2881
2882 // Stylus down on the window
2883 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2884 .deviceId(stylusDeviceId)
2885 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2886 .build());
2887 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2888 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2889
2890 // Subsequent stylus movements are delivered correctly
2891 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2892 .deviceId(stylusDeviceId)
2893 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2894 .build());
2895 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2896 WithCoords(101, 111)));
2897}
2898
2899/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002900 * Two windows: a window on the left and a window on the right.
2901 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2902 * down. Then, on the left window, also place second touch pointer down.
2903 * This test tries to reproduce a crash.
2904 * In the buggy implementation, second pointer down on the left window would cause a crash.
2905 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002906TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002907 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2908 sp<FakeWindowHandle> leftWindow =
2909 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2910 leftWindow->setFrame(Rect(0, 0, 200, 200));
2911
2912 sp<FakeWindowHandle> rightWindow =
2913 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2914 rightWindow->setFrame(Rect(200, 0, 400, 200));
2915
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002916 mDispatcher->onWindowInfosChanged(
2917 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002918
2919 const int32_t touchDeviceId = 4;
2920 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002921
2922 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002923 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2924 .deviceId(mouseDeviceId)
2925 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2926 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002927 leftWindow->consumeMotionEvent(
2928 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2929
2930 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002931 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2932 .deviceId(mouseDeviceId)
2933 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2934 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2935 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002936
2937 leftWindow->consumeMotionEvent(
2938 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2939 leftWindow->consumeMotionEvent(
2940 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2941
Prabir Pradhan678438e2023-04-13 19:32:51 +00002942 mDispatcher->notifyMotion(
2943 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2944 .deviceId(mouseDeviceId)
2945 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2946 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2947 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2948 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002949 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2950
2951 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002952 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2953 .deviceId(touchDeviceId)
2954 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2955 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002956 leftWindow->assertNoEvents();
2957
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002958 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2959
2960 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002961 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2962 .deviceId(touchDeviceId)
2963 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2964 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2965 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002966 // Since this is now a new splittable pointer going down on the left window, and it's coming
2967 // from a different device, the current gesture in the left window (pointer down) should first
2968 // be canceled.
2969 leftWindow->consumeMotionEvent(
2970 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002971 leftWindow->consumeMotionEvent(
2972 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2973 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2974 // current implementation.
2975 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2976 rightWindow->consumeMotionEvent(
2977 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2978
2979 leftWindow->assertNoEvents();
2980 rightWindow->assertNoEvents();
2981}
2982
2983/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002984 * Two windows: a window on the left and a window on the right.
2985 * Mouse is hovered on the left window and stylus is hovered on the right window.
2986 */
2987TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2988 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2989 sp<FakeWindowHandle> leftWindow =
2990 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2991 leftWindow->setFrame(Rect(0, 0, 200, 200));
2992
2993 sp<FakeWindowHandle> rightWindow =
2994 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2995 rightWindow->setFrame(Rect(200, 0, 400, 200));
2996
2997 mDispatcher->onWindowInfosChanged(
2998 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2999
3000 const int32_t stylusDeviceId = 3;
3001 const int32_t mouseDeviceId = 6;
3002
3003 // Start hovering over the left window
3004 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3005 .deviceId(mouseDeviceId)
3006 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
3007 .build());
3008 leftWindow->consumeMotionEvent(
3009 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3010
3011 // Stylus hovered on right window
3012 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3013 .deviceId(stylusDeviceId)
3014 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
3015 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003016 rightWindow->consumeMotionEvent(
3017 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3018
3019 // Subsequent HOVER_MOVE events are dispatched correctly.
3020 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
3021 .deviceId(mouseDeviceId)
3022 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
3023 .build());
3024 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003025 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003026
3027 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3028 .deviceId(stylusDeviceId)
3029 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
3030 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003031 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003032 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003033
3034 leftWindow->assertNoEvents();
3035 rightWindow->assertNoEvents();
3036}
3037
3038/**
3039 * Three windows: a window on the left and a window on the right.
3040 * And a spy window that's positioned above all of them.
3041 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
3042 * Check the stream that's received by the spy.
3043 */
3044TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
3045 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3046
3047 sp<FakeWindowHandle> spyWindow =
3048 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3049 spyWindow->setFrame(Rect(0, 0, 400, 400));
3050 spyWindow->setTrustedOverlay(true);
3051 spyWindow->setSpy(true);
3052
3053 sp<FakeWindowHandle> leftWindow =
3054 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3055 leftWindow->setFrame(Rect(0, 0, 200, 200));
3056
3057 sp<FakeWindowHandle> rightWindow =
3058 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3059
3060 rightWindow->setFrame(Rect(200, 0, 400, 200));
3061
3062 mDispatcher->onWindowInfosChanged(
3063 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3064
3065 const int32_t stylusDeviceId = 1;
3066 const int32_t touchDeviceId = 2;
3067
3068 // Stylus down on the left window
3069 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3070 .deviceId(stylusDeviceId)
3071 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3072 .build());
3073 leftWindow->consumeMotionEvent(
3074 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3075 spyWindow->consumeMotionEvent(
3076 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3077
3078 // Touch down on the right window
3079 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3080 .deviceId(touchDeviceId)
3081 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3082 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003083 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003084 rightWindow->consumeMotionEvent(
3085 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003086
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003087 // Spy window does not receive touch events, because stylus events take precedence, and it
3088 // already has an active stylus gesture.
3089
3090 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003091 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3092 .deviceId(stylusDeviceId)
3093 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3094 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003095 leftWindow->consumeMotionEvent(
3096 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3097 spyWindow->consumeMotionEvent(
3098 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003099
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003100 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003101 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3102 .deviceId(touchDeviceId)
3103 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
3104 .build());
3105 rightWindow->consumeMotionEvent(
3106 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003107
3108 spyWindow->assertNoEvents();
3109 leftWindow->assertNoEvents();
3110 rightWindow->assertNoEvents();
3111}
3112
3113/**
3114 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3115 * both.
3116 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003117 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003118 * At the same time, left and right should be getting independent streams of hovering and touch,
3119 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003120 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003121TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003122 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3123
3124 sp<FakeWindowHandle> spyWindow =
3125 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3126 spyWindow->setFrame(Rect(0, 0, 400, 400));
3127 spyWindow->setTrustedOverlay(true);
3128 spyWindow->setSpy(true);
3129
3130 sp<FakeWindowHandle> leftWindow =
3131 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3132 leftWindow->setFrame(Rect(0, 0, 200, 200));
3133
3134 sp<FakeWindowHandle> rightWindow =
3135 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3136 rightWindow->setFrame(Rect(200, 0, 400, 200));
3137
3138 mDispatcher->onWindowInfosChanged(
3139 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3140
3141 const int32_t stylusDeviceId = 1;
3142 const int32_t touchDeviceId = 2;
3143
3144 // Stylus hover on the left window
3145 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3146 .deviceId(stylusDeviceId)
3147 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3148 .build());
3149 leftWindow->consumeMotionEvent(
3150 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3151 spyWindow->consumeMotionEvent(
3152 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3153
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003154 // Touch down on the right window. Spy doesn't receive this touch because it already has
3155 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003156 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3157 .deviceId(touchDeviceId)
3158 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3159 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003160 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003161 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003162 rightWindow->consumeMotionEvent(
3163 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3164
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003165 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003166 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3167 .deviceId(stylusDeviceId)
3168 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3169 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003170 leftWindow->consumeMotionEvent(
3171 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003172 spyWindow->consumeMotionEvent(
3173 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003174
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003175 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003176 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3177 .deviceId(touchDeviceId)
3178 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3179 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003180 rightWindow->consumeMotionEvent(
3181 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3182
3183 spyWindow->assertNoEvents();
3184 leftWindow->assertNoEvents();
3185 rightWindow->assertNoEvents();
3186}
3187
3188/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003189 * On a single window, use two different devices: mouse and touch.
3190 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3191 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3192 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3193 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3194 * represent a new gesture.
3195 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003196TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003197 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3198 sp<FakeWindowHandle> window =
3199 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3200 window->setFrame(Rect(0, 0, 400, 400));
3201
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003202 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003203
3204 const int32_t touchDeviceId = 4;
3205 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003206
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003207 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003208 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3209 .deviceId(touchDeviceId)
3210 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3211 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003212 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003213 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3214 .deviceId(touchDeviceId)
3215 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3216 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3217 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003218 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003219 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3220 .deviceId(touchDeviceId)
3221 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3222 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3223 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003224 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3225 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3226 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3227
3228 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003229 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3230 .deviceId(mouseDeviceId)
3231 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3232 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3233 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003234
3235 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003236 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003237 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3238
Prabir Pradhan678438e2023-04-13 19:32:51 +00003239 mDispatcher->notifyMotion(
3240 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3241 .deviceId(mouseDeviceId)
3242 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3243 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3244 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3245 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003246 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3247
3248 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003249 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3250 .deviceId(touchDeviceId)
3251 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3252 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3253 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003254 // Since we already canceled this touch gesture, it will be ignored until a completely new
3255 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3256 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3257 // However, mouse movements should continue to work.
3258 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3259 .deviceId(mouseDeviceId)
3260 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3261 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3262 .build());
3263 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3264
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003265 window->assertNoEvents();
3266}
3267
3268/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003269 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3270 * the injected event.
3271 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003272TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003273 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3274 sp<FakeWindowHandle> window =
3275 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3276 window->setFrame(Rect(0, 0, 400, 400));
3277
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003278 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003279
3280 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003281 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3282 // completion.
3283 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003284 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003285 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3286 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003287 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003288 .build()));
3289 window->consumeMotionEvent(
3290 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3291
3292 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3293 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003294 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3295 .deviceId(touchDeviceId)
3296 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3297 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003298
3299 window->consumeMotionEvent(
3300 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3301 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3302}
3303
3304/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003305 * This test is similar to the test above, but the sequence of injected events is different.
3306 *
3307 * Two windows: a window on the left and a window on the right.
3308 * Mouse is hovered over the left window.
3309 * Next, we tap on the left window, where the cursor was last seen.
3310 *
3311 * After that, we inject one finger down onto the right window, and then a second finger down onto
3312 * the left window.
3313 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3314 * window (first), and then another on the left window (second).
3315 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3316 * In the buggy implementation, second finger down on the left window would cause a crash.
3317 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003318TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003319 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3320 sp<FakeWindowHandle> leftWindow =
3321 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3322 leftWindow->setFrame(Rect(0, 0, 200, 200));
3323
3324 sp<FakeWindowHandle> rightWindow =
3325 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3326 rightWindow->setFrame(Rect(200, 0, 400, 200));
3327
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003328 mDispatcher->onWindowInfosChanged(
3329 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003330
3331 const int32_t mouseDeviceId = 6;
3332 const int32_t touchDeviceId = 4;
3333 // Hover over the left window. Keep the cursor there.
3334 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003335 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003336 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3337 AINPUT_SOURCE_MOUSE)
3338 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003339 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003340 .build()));
3341 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3342
3343 // Tap on left window
3344 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003345 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003346 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3347 AINPUT_SOURCE_TOUCHSCREEN)
3348 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003349 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003350 .build()));
3351
3352 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003353 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003354 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3355 AINPUT_SOURCE_TOUCHSCREEN)
3356 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003357 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003358 .build()));
3359 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3360 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3361 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3362
3363 // First finger down on right window
3364 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003365 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003366 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3367 AINPUT_SOURCE_TOUCHSCREEN)
3368 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003369 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003370 .build()));
3371 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3372
3373 // Second finger down on the left window
3374 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003375 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003376 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3377 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003378 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3379 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003380 .build()));
3381 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3382 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3383
3384 // No more events
3385 leftWindow->assertNoEvents();
3386 rightWindow->assertNoEvents();
3387}
3388
3389/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003390 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3391 * While the touch is down, new hover events from the stylus device should be ignored. After the
3392 * touch is gone, stylus hovering should start working again.
3393 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003394TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003395 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3396 sp<FakeWindowHandle> window =
3397 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3398 window->setFrame(Rect(0, 0, 200, 200));
3399
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003400 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003401
3402 const int32_t stylusDeviceId = 5;
3403 const int32_t touchDeviceId = 4;
3404 // Start hovering with stylus
3405 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003406 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003407 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003408 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003409 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003410 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003411 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003412
3413 // Finger down on the window
3414 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003415 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003416 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003417 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003418 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003419 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003420 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003421
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003422 // Continue hovering with stylus.
3423 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003424 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003425 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3426 AINPUT_SOURCE_STYLUS)
3427 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003428 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003429 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003430 // Hovers continue to work
3431 window->consumeMotionEvent(
3432 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003433
3434 // Lift up the finger
3435 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003436 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003437 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3438 AINPUT_SOURCE_TOUCHSCREEN)
3439 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003440 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003441 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003442
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003443 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003444 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003445 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3446 AINPUT_SOURCE_STYLUS)
3447 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003448 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003449 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003450 window->consumeMotionEvent(
3451 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003452 window->assertNoEvents();
3453}
3454
3455/**
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003456 * If stylus is down anywhere on the screen, then touches should not be delivered to windows that
3457 * have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3458 *
3459 * Two windows: one on the left and one on the right.
3460 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3461 * Stylus down on the left window, and then touch down on the right window.
3462 * Check that the right window doesn't get touches while the stylus is down on the left window.
3463 */
3464TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusDownBlocksTouch) {
3465 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3466 sp<FakeWindowHandle> leftWindow =
3467 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3468 ADISPLAY_ID_DEFAULT);
3469 leftWindow->setFrame(Rect(0, 0, 100, 100));
3470
3471 sp<FakeWindowHandle> sbtRightWindow =
3472 sp<FakeWindowHandle>::make(application, mDispatcher,
3473 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3474 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3475 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3476
3477 mDispatcher->onWindowInfosChanged(
3478 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3479
3480 const int32_t stylusDeviceId = 5;
3481 const int32_t touchDeviceId = 4;
3482
3483 // Stylus down in the left window
3484 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3485 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3486 .deviceId(stylusDeviceId)
3487 .build());
3488 leftWindow->consumeMotionEvent(
3489 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3490
3491 // Finger tap on the right window
3492 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3493 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3494 .deviceId(touchDeviceId)
3495 .build());
3496 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3497 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3498 .deviceId(touchDeviceId)
3499 .build());
3500
3501 // The touch should be blocked, because stylus is down somewhere else on screen!
3502 sbtRightWindow->assertNoEvents();
3503
3504 // Continue stylus motion, and ensure it's not impacted.
3505 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3506 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3507 .deviceId(stylusDeviceId)
3508 .build());
3509 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3510 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3511 .deviceId(stylusDeviceId)
3512 .build());
3513 leftWindow->consumeMotionEvent(
3514 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3515 leftWindow->consumeMotionEvent(
3516 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(stylusDeviceId)));
3517
3518 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3519 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3520 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3521 .deviceId(touchDeviceId)
3522 .build());
3523 sbtRightWindow->consumeMotionEvent(
3524 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3525}
3526
3527/**
3528 * If stylus is hovering anywhere on the screen, then touches should not be delivered to windows
3529 * that have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3530 *
3531 * Two windows: one on the left and one on the right.
3532 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3533 * Stylus hover on the left window, and then touch down on the right window.
3534 * Check that the right window doesn't get touches while the stylus is hovering on the left window.
3535 */
3536TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusHoverBlocksTouch) {
3537 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3538 sp<FakeWindowHandle> leftWindow =
3539 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3540 ADISPLAY_ID_DEFAULT);
3541 leftWindow->setFrame(Rect(0, 0, 100, 100));
3542
3543 sp<FakeWindowHandle> sbtRightWindow =
3544 sp<FakeWindowHandle>::make(application, mDispatcher,
3545 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3546 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3547 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3548
3549 mDispatcher->onWindowInfosChanged(
3550 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3551
3552 const int32_t stylusDeviceId = 5;
3553 const int32_t touchDeviceId = 4;
3554
3555 // Stylus hover in the left window
3556 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3557 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3558 .deviceId(stylusDeviceId)
3559 .build());
3560 leftWindow->consumeMotionEvent(
3561 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3562
3563 // Finger tap on the right window
3564 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3565 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3566 .deviceId(touchDeviceId)
3567 .build());
3568 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3569 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3570 .deviceId(touchDeviceId)
3571 .build());
3572
3573 // The touch should be blocked, because stylus is hovering somewhere else on screen!
3574 sbtRightWindow->assertNoEvents();
3575
3576 // Continue stylus motion, and ensure it's not impacted.
3577 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3578 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3579 .deviceId(stylusDeviceId)
3580 .build());
3581 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3582 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3583 .deviceId(stylusDeviceId)
3584 .build());
3585 leftWindow->consumeMotionEvent(
3586 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3587 leftWindow->consumeMotionEvent(
3588 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3589
3590 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3591 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3592 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3593 .deviceId(touchDeviceId)
3594 .build());
3595 sbtRightWindow->consumeMotionEvent(
3596 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3597}
3598
3599/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003600 * A spy window above a window with no input channel.
3601 * Start hovering with a stylus device, and then tap with it.
3602 * Ensure spy window receives the entire sequence.
3603 */
3604TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3605 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3606 sp<FakeWindowHandle> spyWindow =
3607 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3608 spyWindow->setFrame(Rect(0, 0, 200, 200));
3609 spyWindow->setTrustedOverlay(true);
3610 spyWindow->setSpy(true);
3611 sp<FakeWindowHandle> window =
3612 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3613 window->setNoInputChannel(true);
3614 window->setFrame(Rect(0, 0, 200, 200));
3615
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003616 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003617
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003618 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003619 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3620 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3621 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003622 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3623 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003624 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3625 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3626 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003627 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3628
3629 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003630 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3631 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3632 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003633 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3634
3635 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003636 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3637 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3638 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003639 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3640
3641 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003642 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3643 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3644 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003645 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3646 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003647 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3648 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3649 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003650 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3651
3652 // No more events
3653 spyWindow->assertNoEvents();
3654 window->assertNoEvents();
3655}
3656
3657/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003658 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3659 * rejected. But since we already have an ongoing gesture, this event should be processed.
3660 * This prevents inconsistent events being handled inside the dispatcher.
3661 */
3662TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3663 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3664
3665 sp<FakeWindowHandle> window =
3666 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3667 window->setFrame(Rect(0, 0, 200, 200));
3668
3669 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3670
3671 // Start hovering with stylus
3672 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3673 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3674 .build());
3675 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3676
3677 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3678 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3679 .build();
3680 // Make this 'hoverExit' event stale
3681 mFakePolicy->setStaleEventTimeout(100ms);
3682 std::this_thread::sleep_for(100ms);
3683
3684 // It shouldn't be dropped by the dispatcher, even though it's stale.
3685 mDispatcher->notifyMotion(hoverExit);
3686 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3687
3688 // Stylus starts hovering again! There should be no crash.
3689 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3690 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3691 .build());
3692 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3693}
3694
3695/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003696 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3697 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3698 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3699 * While the mouse is down, new move events from the touch device should be ignored.
3700 */
3701TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3702 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3703 sp<FakeWindowHandle> spyWindow =
3704 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3705 spyWindow->setFrame(Rect(0, 0, 200, 200));
3706 spyWindow->setTrustedOverlay(true);
3707 spyWindow->setSpy(true);
3708 sp<FakeWindowHandle> window =
3709 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3710 window->setFrame(Rect(0, 0, 200, 200));
3711
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003712 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003713
3714 const int32_t mouseDeviceId = 7;
3715 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003716
3717 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003718 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3719 .deviceId(mouseDeviceId)
3720 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3721 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003722 spyWindow->consumeMotionEvent(
3723 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3724 window->consumeMotionEvent(
3725 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3726
3727 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003728 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3729 .deviceId(touchDeviceId)
3730 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3731 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003732 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3733 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3734 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3735 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3736
Prabir Pradhan678438e2023-04-13 19:32:51 +00003737 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3738 .deviceId(touchDeviceId)
3739 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3740 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003741 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3742 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3743
3744 // Pilfer the stream
3745 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3746 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3747
Prabir Pradhan678438e2023-04-13 19:32:51 +00003748 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3749 .deviceId(touchDeviceId)
3750 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3751 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003752 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3753
3754 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003755 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3756 .deviceId(mouseDeviceId)
3757 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3758 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3759 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003760
3761 spyWindow->consumeMotionEvent(
3762 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3763 spyWindow->consumeMotionEvent(
3764 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3765 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3766
Prabir Pradhan678438e2023-04-13 19:32:51 +00003767 mDispatcher->notifyMotion(
3768 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3769 .deviceId(mouseDeviceId)
3770 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3771 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3772 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3773 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003774 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3775 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3776
3777 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003778 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3779 .deviceId(mouseDeviceId)
3780 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3781 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3782 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003783 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3784 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3785
3786 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003787 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3788 .deviceId(touchDeviceId)
3789 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3790 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003791
3792 // No more events
3793 spyWindow->assertNoEvents();
3794 window->assertNoEvents();
3795}
3796
3797/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003798 * On the display, have a single window, and also an area where there's no window.
3799 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3800 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3801 */
3802TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3803 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3804 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003805 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003806
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003807 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003808
3809 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003810 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003811
3812 mDispatcher->waitForIdle();
3813 window->assertNoEvents();
3814
3815 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003816 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003817 mDispatcher->waitForIdle();
3818 window->consumeMotionDown();
3819}
3820
3821/**
3822 * Same test as above, but instead of touching the empty space, the first touch goes to
3823 * non-touchable window.
3824 */
3825TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3826 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3827 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003828 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003829 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3830 window1->setTouchable(false);
3831 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003832 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003833 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3834
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003835 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003836
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003837 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003838 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003839
3840 mDispatcher->waitForIdle();
3841 window1->assertNoEvents();
3842 window2->assertNoEvents();
3843
3844 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003845 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003846 mDispatcher->waitForIdle();
3847 window2->consumeMotionDown();
3848}
3849
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003850/**
3851 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3852 * to the event time of the first ACTION_DOWN sent to the particular window.
3853 */
3854TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3855 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3856 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003857 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003858 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3859 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003860 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003861 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3862
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003863 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003864
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003865 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003866 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003867
3868 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003869
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08003870 std::unique_ptr<MotionEvent> motionEvent1 = window1->consumeMotionEvent();
3871 ASSERT_NE(nullptr, motionEvent1);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003872 window2->assertNoEvents();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08003873 nsecs_t downTimeForWindow1 = motionEvent1->getDownTime();
3874 ASSERT_EQ(motionEvent1->getDownTime(), motionEvent1->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003875
3876 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003877 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003878 mDispatcher->waitForIdle();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08003879 std::unique_ptr<MotionEvent> motionEvent2 = window2->consumeMotionEvent();
3880 ASSERT_NE(nullptr, motionEvent2);
3881 nsecs_t downTimeForWindow2 = motionEvent2->getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003882 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08003883 ASSERT_EQ(motionEvent2->getDownTime(), motionEvent2->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003884
3885 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003886 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003887 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003888 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003889
3890 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003891 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003892 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003893 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003894
3895 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3896 window1->consumeMotionMove();
3897 window1->assertNoEvents();
3898
3899 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003900 mDispatcher->notifyMotion(
3901 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003902 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003903 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003904
Prabir Pradhan678438e2023-04-13 19:32:51 +00003905 mDispatcher->notifyMotion(
3906 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003907 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003908 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003909}
3910
Garfield Tandf26e862020-07-01 20:18:19 -07003911TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003912 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003913 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003914 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003915 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003916 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003917 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003918 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003919
3920 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3921
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003922 mDispatcher->onWindowInfosChanged(
3923 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003924
3925 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003926 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003927 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003928 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3929 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003930 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003931 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003932 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003933
3934 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003935 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003936 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003937 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3938 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003939 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003940 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003941 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3942 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003943
3944 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003945 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003946 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003947 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3948 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003949 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003950 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003951 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3952 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003953
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003954 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003955 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003956 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3957 AINPUT_SOURCE_MOUSE)
3958 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3959 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003960 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003961 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003962 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003963
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003964 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003965 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003966 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3967 AINPUT_SOURCE_MOUSE)
3968 .buttonState(0)
3969 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003970 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003971 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003972 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003973
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003974 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003975 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003976 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3977 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003978 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003979 .build()));
3980 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3981
3982 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003983 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003984 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003985 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3986 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003987 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003988 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003989 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003990
3991 // No more events
3992 windowLeft->assertNoEvents();
3993 windowRight->assertNoEvents();
3994}
3995
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003996/**
3997 * Put two fingers down (and don't release them) and click the mouse button.
3998 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3999 * currently active gesture should be canceled, and the new one should proceed.
4000 */
4001TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
4002 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4003 sp<FakeWindowHandle> window =
4004 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4005 window->setFrame(Rect(0, 0, 600, 800));
4006
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004007 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004008
4009 const int32_t touchDeviceId = 4;
4010 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004011
4012 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004013 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4014 .deviceId(touchDeviceId)
4015 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4016 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004017
Prabir Pradhan678438e2023-04-13 19:32:51 +00004018 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4019 .deviceId(touchDeviceId)
4020 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4021 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4022 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004023 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4024 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4025
4026 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00004027 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4028 .deviceId(mouseDeviceId)
4029 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4030 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4031 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004032 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
4033 WithPointerCount(2u)));
4034 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4035
Prabir Pradhan678438e2023-04-13 19:32:51 +00004036 mDispatcher->notifyMotion(
4037 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4038 .deviceId(mouseDeviceId)
4039 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4040 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4041 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4042 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004043 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4044
4045 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4046 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004047 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4048 .deviceId(touchDeviceId)
4049 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4050 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4051 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004052 window->assertNoEvents();
4053}
4054
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004055TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
4056 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4057
4058 sp<FakeWindowHandle> spyWindow =
4059 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4060 spyWindow->setFrame(Rect(0, 0, 600, 800));
4061 spyWindow->setTrustedOverlay(true);
4062 spyWindow->setSpy(true);
4063 sp<FakeWindowHandle> window =
4064 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4065 window->setFrame(Rect(0, 0, 600, 800));
4066
4067 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004068 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004069
4070 // Send mouse cursor to the window
4071 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004072 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004073 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4074 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004075 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004076 .build()));
4077
4078 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4079 WithSource(AINPUT_SOURCE_MOUSE)));
4080 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4081 WithSource(AINPUT_SOURCE_MOUSE)));
4082
4083 window->assertNoEvents();
4084 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004085}
4086
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004087TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
4088 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4089
4090 sp<FakeWindowHandle> spyWindow =
4091 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4092 spyWindow->setFrame(Rect(0, 0, 600, 800));
4093 spyWindow->setTrustedOverlay(true);
4094 spyWindow->setSpy(true);
4095 sp<FakeWindowHandle> window =
4096 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4097 window->setFrame(Rect(0, 0, 600, 800));
4098
4099 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004100 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004101
4102 // Send mouse cursor to the window
4103 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004104 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004105 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4106 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004107 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004108 .build()));
4109
4110 // Move mouse cursor
4111 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004112 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004113 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4114 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004115 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004116 .build()));
4117
4118 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4119 WithSource(AINPUT_SOURCE_MOUSE)));
4120 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4121 WithSource(AINPUT_SOURCE_MOUSE)));
4122 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4123 WithSource(AINPUT_SOURCE_MOUSE)));
4124 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4125 WithSource(AINPUT_SOURCE_MOUSE)));
4126 // Touch down on the window
4127 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004128 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004129 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4130 AINPUT_SOURCE_TOUCHSCREEN)
4131 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004132 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004133 .build()));
4134 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4135 WithSource(AINPUT_SOURCE_MOUSE)));
4136 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4137 WithSource(AINPUT_SOURCE_MOUSE)));
4138 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4139 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4140 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4141 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4142
4143 // pilfer the motion, retaining the gesture on the spy window.
4144 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4145 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4146 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4147
4148 // Touch UP on the window
4149 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004150 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004151 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4152 AINPUT_SOURCE_TOUCHSCREEN)
4153 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004154 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004155 .build()));
4156 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4157 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4158
4159 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4160 // to send a new gesture. It should again go to both windows (spy and the window below), just
4161 // like the first gesture did, before pilfering. The window configuration has not changed.
4162
4163 // One more tap - DOWN
4164 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004165 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004166 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4167 AINPUT_SOURCE_TOUCHSCREEN)
4168 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004169 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004170 .build()));
4171 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4172 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4173 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4174 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4175
4176 // Touch UP on the window
4177 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004178 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004179 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4180 AINPUT_SOURCE_TOUCHSCREEN)
4181 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004182 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004183 .build()));
4184 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4185 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4186 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4187 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4188
4189 window->assertNoEvents();
4190 spyWindow->assertNoEvents();
4191}
4192
Garfield Tandf26e862020-07-01 20:18:19 -07004193// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
4194// directly in this test.
4195TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004196 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07004197 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004198 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004199 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004200
4201 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4202
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004203 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004204
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004205 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004206 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004207 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4208 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004209 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004210 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004211 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004212 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004213 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004214 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004215 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4216 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004217 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004218 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004219 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4220 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004221
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004222 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004223 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004224 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4225 AINPUT_SOURCE_MOUSE)
4226 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4227 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004228 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004229 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004230 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004231
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004232 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004233 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004234 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4235 AINPUT_SOURCE_MOUSE)
4236 .buttonState(0)
4237 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004238 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004239 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004240 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004241
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004242 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004243 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004244 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4245 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004246 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004247 .build()));
4248 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
4249
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07004250 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
4251 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
4252 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004253 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004254 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
4255 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004256 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004257 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004258 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004259}
4260
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004261/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004262 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
4263 * is generated.
4264 */
4265TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
4266 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4267 sp<FakeWindowHandle> window =
4268 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4269 window->setFrame(Rect(0, 0, 1200, 800));
4270
4271 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4272
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004273 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004274
4275 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004276 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004277 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4278 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004279 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004280 .build()));
4281 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4282
4283 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004284 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004285 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4286}
4287
4288/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004289 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4290 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004291TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4292 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4293 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004294 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4295 sp<FakeWindowHandle> window =
4296 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4297 window->setFrame(Rect(0, 0, 1200, 800));
4298
4299 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4300
4301 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4302
4303 MotionEventBuilder hoverEnterBuilder =
4304 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4305 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4306 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4307 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4308 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4309 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4310 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4311 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4312 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4313}
4314
4315/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004316 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4317 */
4318TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4319 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4320 sp<FakeWindowHandle> window =
4321 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4322 window->setFrame(Rect(0, 0, 100, 100));
4323
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004324 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004325
4326 const int32_t mouseDeviceId = 7;
4327 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004328
4329 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004330 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4331 .deviceId(mouseDeviceId)
4332 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4333 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004334 window->consumeMotionEvent(
4335 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4336
4337 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004338 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4339 .deviceId(touchDeviceId)
4340 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4341 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004342
4343 window->consumeMotionEvent(
4344 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4345 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4346}
4347
4348/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004349 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004350 * The tap causes a HOVER_EXIT event to be generated because the current event
4351 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004352 */
4353TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4354 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4355 sp<FakeWindowHandle> window =
4356 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4357 window->setFrame(Rect(0, 0, 100, 100));
4358
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004359 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004360 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4361 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4362 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004363 ASSERT_NO_FATAL_FAILURE(
4364 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4365 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004366
4367 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004368 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4369 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4370 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004371 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004372 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4373 WithSource(AINPUT_SOURCE_MOUSE))));
4374
4375 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004376 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4377 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4378
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004379 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4380 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4381 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004382 ASSERT_NO_FATAL_FAILURE(
4383 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4384 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4385}
4386
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004387TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4388 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4389 sp<FakeWindowHandle> windowDefaultDisplay =
4390 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4391 ADISPLAY_ID_DEFAULT);
4392 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4393 sp<FakeWindowHandle> windowSecondDisplay =
4394 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4395 SECOND_DISPLAY_ID);
4396 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4397
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004398 mDispatcher->onWindowInfosChanged(
4399 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004400
4401 // Set cursor position in window in default display and check that hover enter and move
4402 // events are generated.
4403 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004404 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004405 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4406 AINPUT_SOURCE_MOUSE)
4407 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004408 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004409 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004410 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004411
4412 // Remove all windows in secondary display and check that no event happens on window in
4413 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004414 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4415
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004416 windowDefaultDisplay->assertNoEvents();
4417
4418 // Move cursor position in window in default display and check that only hover move
4419 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004420 mDispatcher->onWindowInfosChanged(
4421 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004422 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004423 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004424 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4425 AINPUT_SOURCE_MOUSE)
4426 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004427 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004428 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004429 windowDefaultDisplay->consumeMotionEvent(
4430 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4431 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004432 windowDefaultDisplay->assertNoEvents();
4433}
4434
Garfield Tan00f511d2019-06-12 16:55:40 -07004435TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004436 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004437
4438 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004439 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004440 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004441 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004442 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004443 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004444
4445 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4446
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004447 mDispatcher->onWindowInfosChanged(
4448 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004449
4450 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4451 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004452 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004453 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004454 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004455 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004456 windowRight->assertNoEvents();
4457}
4458
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004459TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004460 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004461 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4462 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004463 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004464
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004465 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004466 setFocusedWindow(window);
4467
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004468 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004469
Prabir Pradhan678438e2023-04-13 19:32:51 +00004470 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004471
4472 // Window should receive key down event.
4473 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4474
4475 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4476 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004477 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004478 window->consumeKeyUp(ADISPLAY_ID_DEFAULT, AKEY_EVENT_FLAG_CANCELED);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004479}
4480
4481TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004482 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004483 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4484 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004485
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004486 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004487
Prabir Pradhan678438e2023-04-13 19:32:51 +00004488 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4489 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004490
4491 // Window should receive motion down event.
4492 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4493
4494 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4495 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004496 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004497 window->consumeMotionEvent(
4498 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004499}
4500
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004501TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4502 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4503 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4504 "Fake Window", ADISPLAY_ID_DEFAULT);
4505
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004506 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004507
4508 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4509 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4510 .build());
4511
4512 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4513
4514 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4515 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4516 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4517
4518 // After the device has been reset, a new hovering stream can be sent to the window
4519 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4520 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4521 .build());
4522 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4523}
4524
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004525TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4526 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004527 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4528 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004529 window->setFocusable(true);
4530
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004531 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004532 setFocusedWindow(window);
4533
4534 window->consumeFocusEvent(true);
4535
Prabir Pradhan678438e2023-04-13 19:32:51 +00004536 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004537 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4538 const nsecs_t injectTime = keyArgs.eventTime;
4539 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004540 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004541 // The dispatching time should be always greater than or equal to intercept key timeout.
4542 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4543 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4544 std::chrono::nanoseconds(interceptKeyTimeout).count());
4545}
4546
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004547/**
4548 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4549 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004550TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4551 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004552 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4553 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004554 window->setFocusable(true);
4555
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004556 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004557 setFocusedWindow(window);
4558
4559 window->consumeFocusEvent(true);
4560
Prabir Pradhan678438e2023-04-13 19:32:51 +00004561 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004562 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004563
4564 // Set a value that's significantly larger than the default consumption timeout. If the
4565 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4566 mFakePolicy->setInterceptKeyTimeout(600ms);
4567 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4568 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004569 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4570}
4571
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004572/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004573 * Two windows. First is a regular window. Second does not overlap with the first, and has
4574 * WATCH_OUTSIDE_TOUCH.
4575 * Both windows are owned by the same UID.
4576 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4577 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4578 */
4579TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4580 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004581 sp<FakeWindowHandle> window =
4582 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004583 window->setFrame(Rect{0, 0, 100, 100});
4584
4585 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004586 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004587 ADISPLAY_ID_DEFAULT);
4588 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4589 outsideWindow->setWatchOutsideTouch(true);
4590 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004591 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004592
4593 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004594 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4595 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4596 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004597 window->consumeMotionDown();
4598 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4599 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4600 outsideWindow->consumeMotionEvent(
4601 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00004602
4603 // Ensure outsideWindow doesn't get any more events for the gesture.
4604 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4605 ADISPLAY_ID_DEFAULT, {PointF{51, 51}}));
4606 window->consumeMotionMove();
4607 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004608}
4609
4610/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004611 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4612 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4613 * ACTION_OUTSIDE event is sent per gesture.
4614 */
4615TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4616 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4617 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004618 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4619 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004620 window->setWatchOutsideTouch(true);
4621 window->setFrame(Rect{0, 0, 100, 100});
4622 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004623 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4624 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004625 secondWindow->setFrame(Rect{100, 100, 200, 200});
4626 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004627 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4628 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004629 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004630 mDispatcher->onWindowInfosChanged(
4631 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004632
4633 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004634 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4635 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4636 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004637 window->assertNoEvents();
4638 secondWindow->assertNoEvents();
4639
4640 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4641 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004642 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4643 ADISPLAY_ID_DEFAULT,
4644 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004645 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4646 window->consumeMotionEvent(
4647 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004648 secondWindow->consumeMotionDown();
4649 thirdWindow->assertNoEvents();
4650
4651 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4652 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004653 mDispatcher->notifyMotion(
4654 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4655 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004656 window->assertNoEvents();
4657 secondWindow->consumeMotionMove();
4658 thirdWindow->consumeMotionDown();
4659}
4660
Prabir Pradhan814fe082022-07-22 20:22:18 +00004661TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4662 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004663 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4664 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004665 window->setFocusable(true);
4666
Patrick Williamsd828f302023-04-28 17:52:08 -05004667 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004668 setFocusedWindow(window);
4669
4670 window->consumeFocusEvent(true);
4671
Prabir Pradhan678438e2023-04-13 19:32:51 +00004672 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4673 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4674 mDispatcher->notifyKey(keyDown);
4675 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004676
4677 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4678 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4679
4680 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004681 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004682
4683 window->consumeFocusEvent(false);
4684
Prabir Pradhan678438e2023-04-13 19:32:51 +00004685 mDispatcher->notifyKey(keyDown);
4686 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004687 window->assertNoEvents();
4688}
4689
Arthur Hung96483742022-11-15 03:30:48 +00004690TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4691 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4692 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4693 "Fake Window", ADISPLAY_ID_DEFAULT);
4694 // Ensure window is non-split and have some transform.
4695 window->setPreventSplitting(true);
4696 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004697 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004698
4699 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004700 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004701 {50, 50}))
4702 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4703 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4704
4705 const MotionEvent secondFingerDownEvent =
4706 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4707 .displayId(ADISPLAY_ID_DEFAULT)
4708 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004709 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4710 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004711 .build();
4712 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004713 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004714 InputEventInjectionSync::WAIT_FOR_RESULT))
4715 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4716
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004717 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
4718 ASSERT_NE(nullptr, event);
4719 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4720 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4721 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4722 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4723 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
Arthur Hung96483742022-11-15 03:30:48 +00004724}
4725
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004726/**
4727 * Two windows: a splittable and a non-splittable.
4728 * The non-splittable window shouldn't receive any "incomplete" gestures.
4729 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4730 * The second pointer should be dropped because the initial window is splittable, so it won't get
4731 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4732 * "incomplete" gestures.
4733 */
4734TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4735 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4736 sp<FakeWindowHandle> leftWindow =
4737 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4738 ADISPLAY_ID_DEFAULT);
4739 leftWindow->setPreventSplitting(false);
4740 leftWindow->setFrame(Rect(0, 0, 100, 100));
4741 sp<FakeWindowHandle> rightWindow =
4742 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4743 ADISPLAY_ID_DEFAULT);
4744 rightWindow->setPreventSplitting(true);
4745 rightWindow->setFrame(Rect(100, 100, 200, 200));
4746 mDispatcher->onWindowInfosChanged(
4747 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4748
4749 // Touch down on left, splittable window
4750 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4751 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4752 .build());
4753 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4754
4755 mDispatcher->notifyMotion(
4756 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4757 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4758 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4759 .build());
4760 leftWindow->assertNoEvents();
4761 rightWindow->assertNoEvents();
4762}
4763
Harry Cuttsb166c002023-05-09 13:06:05 +00004764TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4765 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4766 sp<FakeWindowHandle> window =
4767 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4768 window->setFrame(Rect(0, 0, 400, 400));
4769 sp<FakeWindowHandle> trustedOverlay =
4770 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4771 ADISPLAY_ID_DEFAULT);
4772 trustedOverlay->setSpy(true);
4773 trustedOverlay->setTrustedOverlay(true);
4774
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004775 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004776
4777 // Start a three-finger touchpad swipe
4778 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4779 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4780 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4781 .build());
4782 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4783 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4784 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4785 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4786 .build());
4787 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4788 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4789 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4790 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4791 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4792 .build());
4793
4794 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4795 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4796 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4797
4798 // Move the swipe a bit
4799 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4800 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4801 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4802 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4803 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4804 .build());
4805
4806 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4807
4808 // End the swipe
4809 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4810 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4811 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4812 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4813 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4814 .build());
4815 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4816 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4817 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4818 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4819 .build());
4820 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4821 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4822 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4823 .build());
4824
4825 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4826 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4827 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4828
4829 window->assertNoEvents();
4830}
4831
4832TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4833 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4834 sp<FakeWindowHandle> window =
4835 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4836 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004837 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004838
4839 // Start a three-finger touchpad swipe
4840 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4841 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4842 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4843 .build());
4844 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4845 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4846 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4847 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4848 .build());
4849 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4850 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4851 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4852 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4853 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4854 .build());
4855
4856 // Move the swipe a bit
4857 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4858 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4859 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4860 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4861 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4862 .build());
4863
4864 // End the swipe
4865 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4866 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4867 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4868 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4869 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4870 .build());
4871 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4872 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4873 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4874 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4875 .build());
4876 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4877 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4878 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4879 .build());
4880
4881 window->assertNoEvents();
4882}
4883
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004884/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004885 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4886 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004887 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004888 */
4889TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4890 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4891 sp<FakeWindowHandle> window =
4892 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4893 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004894 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004895
4896 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4897 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4898 .downTime(baseTime + 10)
4899 .eventTime(baseTime + 10)
4900 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4901 .build());
4902
4903 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4904
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004905 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004906 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004907
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004908 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004909
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004910 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4911 .downTime(baseTime + 10)
4912 .eventTime(baseTime + 30)
4913 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4914 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4915 .build());
4916
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004917 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4918
4919 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004920 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4921 .downTime(baseTime + 10)
4922 .eventTime(baseTime + 40)
4923 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4924 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4925 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004926
4927 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4928
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004929 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4930 .downTime(baseTime + 10)
4931 .eventTime(baseTime + 50)
4932 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4933 .build());
4934
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004935 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4936
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004937 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4938 .downTime(baseTime + 60)
4939 .eventTime(baseTime + 60)
4940 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4941 .build());
4942
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004943 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004944}
4945
4946/**
Hu Guo771a7692023-09-17 20:51:08 +08004947 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4948 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4949 * its coordinates should be converted by the transform of the windows of target screen.
4950 */
4951TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4952 // This case will create a window and a spy window on the default display and mirror
4953 // window on the second display. cancel event is sent through spy window pilferPointers
4954 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4955
4956 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4957 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4958 spyWindowDefaultDisplay->setTrustedOverlay(true);
4959 spyWindowDefaultDisplay->setSpy(true);
4960
4961 sp<FakeWindowHandle> windowDefaultDisplay =
4962 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4963 ADISPLAY_ID_DEFAULT);
4964 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4965
4966 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4967 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4968
4969 // Add the windows to the dispatcher
4970 mDispatcher->onWindowInfosChanged(
4971 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4972 *windowSecondDisplay->getInfo()},
4973 {},
4974 0,
4975 0});
4976
4977 // Send down to ADISPLAY_ID_DEFAULT
4978 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4979 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4980 {100, 100}))
4981 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4982
4983 spyWindowDefaultDisplay->consumeMotionDown();
4984 windowDefaultDisplay->consumeMotionDown();
4985
4986 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4987
4988 // windowDefaultDisplay gets cancel
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004989 std::unique_ptr<MotionEvent> event = windowDefaultDisplay->consumeMotionEvent();
4990 ASSERT_NE(nullptr, event);
4991 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
Hu Guo771a7692023-09-17 20:51:08 +08004992
4993 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4994 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4995 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4996 // SECOND_DISPLAY_ID, the x and y coordinates are 200
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004997 EXPECT_EQ(100, event->getX(0));
4998 EXPECT_EQ(100, event->getY(0));
Hu Guo771a7692023-09-17 20:51:08 +08004999}
5000
5001/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005002 * Ensure the correct coordinate spaces are used by InputDispatcher.
5003 *
5004 * InputDispatcher works in the display space, so its coordinate system is relative to the display
5005 * panel. Windows get events in the window space, and get raw coordinates in the logical display
5006 * space.
5007 */
5008class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
5009public:
5010 void SetUp() override {
5011 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005012 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005013 }
5014
5015 void addDisplayInfo(int displayId, const ui::Transform& transform) {
5016 gui::DisplayInfo info;
5017 info.displayId = displayId;
5018 info.transform = transform;
5019 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05005020 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005021 }
5022
5023 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
5024 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05005025 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005026 }
5027
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005028 void removeAllWindowsAndDisplays() {
5029 mDisplayInfos.clear();
5030 mWindowInfos.clear();
5031 }
5032
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005033 // Set up a test scenario where the display has a scaled projection and there are two windows
5034 // on the display.
5035 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
5036 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
5037 // respectively.
5038 ui::Transform displayTransform;
5039 displayTransform.set(2, 0, 0, 4);
5040 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5041
5042 std::shared_ptr<FakeApplicationHandle> application =
5043 std::make_shared<FakeApplicationHandle>();
5044
5045 // Add two windows to the display. Their frames are represented in the display space.
5046 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005047 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5048 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005049 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
5050 addWindow(firstWindow);
5051
5052 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005053 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5054 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005055 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
5056 addWindow(secondWindow);
5057 return {std::move(firstWindow), std::move(secondWindow)};
5058 }
5059
5060private:
5061 std::vector<gui::DisplayInfo> mDisplayInfos;
5062 std::vector<gui::WindowInfo> mWindowInfos;
5063};
5064
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005065TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005066 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5067 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005068 // selected so that if the hit test was performed with the point and the bounds being in
5069 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005070 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5071 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5072 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005073
5074 firstWindow->consumeMotionDown();
5075 secondWindow->assertNoEvents();
5076}
5077
5078// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
5079// the event should be treated as being in the logical display space.
5080TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
5081 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5082 // Send down to the first window. The point is represented in the logical display space. The
5083 // point is selected so that if the hit test was done in logical display space, then it would
5084 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005085 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005086 PointF{75 * 2, 55 * 4});
5087
5088 firstWindow->consumeMotionDown();
5089 secondWindow->assertNoEvents();
5090}
5091
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005092// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
5093// event should be treated as being in the logical display space.
5094TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
5095 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5096
5097 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5098 ui::Transform injectedEventTransform;
5099 injectedEventTransform.set(matrix);
5100 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
5101 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
5102
5103 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5104 .displayId(ADISPLAY_ID_DEFAULT)
5105 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005106 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005107 .x(untransformedPoint.x)
5108 .y(untransformedPoint.y))
5109 .build();
5110 event.transform(matrix);
5111
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005112 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005113 InputEventInjectionSync::WAIT_FOR_RESULT);
5114
5115 firstWindow->consumeMotionDown();
5116 secondWindow->assertNoEvents();
5117}
5118
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005119TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
5120 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5121
5122 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005123 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5124 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5125 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005126
5127 firstWindow->assertNoEvents();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005128 std::unique_ptr<MotionEvent> event = secondWindow->consumeMotionEvent();
5129 ASSERT_NE(nullptr, event);
5130 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005131
5132 // Ensure that the events from the "getRaw" API are in logical display coordinates.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005133 EXPECT_EQ(300, event->getRawX(0));
5134 EXPECT_EQ(880, event->getRawY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005135
5136 // Ensure that the x and y values are in the window's coordinate space.
5137 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
5138 // the logical display space. This will be the origin of the window space.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005139 EXPECT_EQ(100, event->getX(0));
5140 EXPECT_EQ(80, event->getY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005141}
5142
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005143TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
5144 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5145 // The monitor will always receive events in the logical display's coordinate space, because
5146 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00005147 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005148
5149 // Send down to the first window.
5150 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5151 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5152 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5153 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5154
5155 // Second pointer goes down on second window.
5156 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5157 ADISPLAY_ID_DEFAULT,
5158 {PointF{50, 100}, PointF{150, 220}}));
5159 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
5160 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
5161 {1, PointF{300, 880}}};
5162 monitor.consumeMotionEvent(
5163 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
5164
5165 mDispatcher->cancelCurrentTouch();
5166
5167 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5168 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
5169 monitor.consumeMotionEvent(
5170 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
5171}
5172
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005173TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
5174 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5175
5176 // Send down to the first window.
5177 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5178 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5179 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5180
5181 // The pointer is transferred to the second window, and the second window receives it in the
5182 // correct coordinate space.
5183 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5184 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5185 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
5186}
5187
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005188TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
5189 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5190
5191 // Send hover move to the second window, and ensure it shows up as hover enter.
5192 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5193 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5194 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5195 WithCoords(100, 80), WithRawCoords(300, 880)));
5196
5197 // Touch down at the same location and ensure a hover exit is synthesized.
5198 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5199 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5200 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5201 WithRawCoords(300, 880)));
5202 secondWindow->consumeMotionEvent(
5203 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5204 secondWindow->assertNoEvents();
5205 firstWindow->assertNoEvents();
5206}
5207
Prabir Pradhan453ae732023-10-13 14:30:14 +00005208// Same as above, but while the window is being mirrored.
5209TEST_F(InputDispatcherDisplayProjectionTest,
5210 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
5211 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5212
5213 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5214 ui::Transform secondDisplayTransform;
5215 secondDisplayTransform.set(matrix);
5216 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5217
5218 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5219 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5220 addWindow(secondWindowClone);
5221
5222 // Send hover move to the second window, and ensure it shows up as hover enter.
5223 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5224 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5225 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5226 WithCoords(100, 80), WithRawCoords(300, 880)));
5227
5228 // Touch down at the same location and ensure a hover exit is synthesized for the correct
5229 // display.
5230 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5231 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5232 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5233 WithRawCoords(300, 880)));
5234 secondWindow->consumeMotionEvent(
5235 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5236 secondWindow->assertNoEvents();
5237 firstWindow->assertNoEvents();
5238}
5239
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005240TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
5241 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5242
5243 // Send hover enter to second window
5244 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5245 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5246 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5247 WithCoords(100, 80), WithRawCoords(300, 880)));
5248
5249 mDispatcher->cancelCurrentTouch();
5250
5251 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5252 WithRawCoords(300, 880)));
5253 secondWindow->assertNoEvents();
5254 firstWindow->assertNoEvents();
5255}
5256
Prabir Pradhan453ae732023-10-13 14:30:14 +00005257// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00005258TEST_F(InputDispatcherDisplayProjectionTest,
5259 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
5260 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5261
5262 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5263 ui::Transform secondDisplayTransform;
5264 secondDisplayTransform.set(matrix);
5265 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5266
5267 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5268 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5269 addWindow(secondWindowClone);
5270
5271 // Send hover enter to second window
5272 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5273 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5274 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5275 WithCoords(100, 80), WithRawCoords(300, 880),
5276 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5277
5278 mDispatcher->cancelCurrentTouch();
5279
5280 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
5281 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5282 WithRawCoords(300, 880),
5283 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5284 secondWindow->assertNoEvents();
5285 firstWindow->assertNoEvents();
5286}
5287
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005288/** Ensure consistent behavior of InputDispatcher in all orientations. */
5289class InputDispatcherDisplayOrientationFixture
5290 : public InputDispatcherDisplayProjectionTest,
5291 public ::testing::WithParamInterface<ui::Rotation> {};
5292
5293// This test verifies the touchable region of a window for all rotations of the display by tapping
5294// in different locations on the display, specifically points close to the four corners of a
5295// window.
5296TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
5297 constexpr static int32_t displayWidth = 400;
5298 constexpr static int32_t displayHeight = 800;
5299
5300 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5301
5302 const auto rotation = GetParam();
5303
5304 // Set up the display with the specified rotation.
5305 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5306 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5307 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5308 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5309 logicalDisplayWidth, logicalDisplayHeight);
5310 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5311
5312 // Create a window with its bounds determined in the logical display.
5313 const Rect frameInLogicalDisplay(100, 100, 200, 300);
5314 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
5315 sp<FakeWindowHandle> window =
5316 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5317 window->setFrame(frameInDisplay, displayTransform);
5318 addWindow(window);
5319
5320 // The following points in logical display space should be inside the window.
5321 static const std::array<vec2, 4> insidePoints{
5322 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5323 for (const auto pointInsideWindow : insidePoints) {
5324 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
5325 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005326 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5327 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5328 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005329 window->consumeMotionDown();
5330
Prabir Pradhan678438e2023-04-13 19:32:51 +00005331 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5332 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5333 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005334 window->consumeMotionUp();
5335 }
5336
5337 // The following points in logical display space should be outside the window.
5338 static const std::array<vec2, 5> outsidePoints{
5339 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
5340 for (const auto pointOutsideWindow : outsidePoints) {
5341 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
5342 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005343 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5344 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5345 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005346
Prabir Pradhan678438e2023-04-13 19:32:51 +00005347 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5348 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5349 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005350 }
5351 window->assertNoEvents();
5352}
5353
5354// Run the precision tests for all rotations.
5355INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
5356 InputDispatcherDisplayOrientationFixture,
5357 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
5358 ui::ROTATION_270),
5359 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
5360 return ftl::enum_string(testParamInfo.param);
5361 });
5362
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005363using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
5364 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005365
5366class TransferTouchFixture : public InputDispatcherTest,
5367 public ::testing::WithParamInterface<TransferFunction> {};
5368
5369TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07005370 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005371
5372 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005373 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005374 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5375 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005376 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005377 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005378 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5379 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005380 sp<FakeWindowHandle> wallpaper =
5381 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
5382 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005383 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005384 mDispatcher->onWindowInfosChanged(
5385 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005386
5387 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005388 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5389 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005390
Svet Ganov5d3bc372020-01-26 23:11:07 -08005391 // Only the first window should get the down event
5392 firstWindow->consumeMotionDown();
5393 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005394 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005395
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005396 // Transfer touch to the second window
5397 TransferFunction f = GetParam();
5398 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5399 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005400 // The first window gets cancel and the second gets down
5401 firstWindow->consumeMotionCancel();
5402 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005403 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005404
5405 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005406 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5407 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005408 // The first window gets no events and the second gets up
5409 firstWindow->assertNoEvents();
5410 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005411 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005412}
5413
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005414/**
5415 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
5416 * from. When we have spy windows, there are several windows to choose from: either spy, or the
5417 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
5418 * natural to the user.
5419 * In this test, we are sending a pointer to both spy window and first window. We then try to
5420 * transfer touch to the second window. The dispatcher should identify the first window as the
5421 * one that should lose the gesture, and therefore the action should be to move the gesture from
5422 * the first window to the second.
5423 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
5424 * the other API, as well.
5425 */
5426TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5427 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5428
5429 // Create a couple of windows + a spy window
5430 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005431 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005432 spyWindow->setTrustedOverlay(true);
5433 spyWindow->setSpy(true);
5434 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005435 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005436 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005437 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005438
5439 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005440 mDispatcher->onWindowInfosChanged(
5441 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005442
5443 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005444 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5445 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005446 // Only the first window and spy should get the down event
5447 spyWindow->consumeMotionDown();
5448 firstWindow->consumeMotionDown();
5449
5450 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
5451 // if f === 'transferTouch'.
5452 TransferFunction f = GetParam();
5453 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5454 ASSERT_TRUE(success);
5455 // The first window gets cancel and the second gets down
5456 firstWindow->consumeMotionCancel();
5457 secondWindow->consumeMotionDown();
5458
5459 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005460 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5461 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005462 // The first window gets no events and the second+spy get up
5463 firstWindow->assertNoEvents();
5464 spyWindow->consumeMotionUp();
5465 secondWindow->consumeMotionUp();
5466}
5467
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005468TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005469 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005470
5471 PointF touchPoint = {10, 10};
5472
5473 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005474 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005475 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5476 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005477 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005478 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005479 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5480 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005481 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005482
5483 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005484 mDispatcher->onWindowInfosChanged(
5485 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005486
5487 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005488 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5489 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5490 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005491 // Only the first window should get the down event
5492 firstWindow->consumeMotionDown();
5493 secondWindow->assertNoEvents();
5494
5495 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005496 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5497 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005498 // Only the first window should get the pointer down event
5499 firstWindow->consumeMotionPointerDown(1);
5500 secondWindow->assertNoEvents();
5501
5502 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005503 TransferFunction f = GetParam();
5504 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5505 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005506 // The first window gets cancel and the second gets down and pointer down
5507 firstWindow->consumeMotionCancel();
5508 secondWindow->consumeMotionDown();
5509 secondWindow->consumeMotionPointerDown(1);
5510
5511 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005512 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5513 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005514 // The first window gets nothing and the second gets pointer up
5515 firstWindow->assertNoEvents();
5516 secondWindow->consumeMotionPointerUp(1);
5517
5518 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005519 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5520 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005521 // The first window gets nothing and the second gets up
5522 firstWindow->assertNoEvents();
5523 secondWindow->consumeMotionUp();
5524}
5525
Arthur Hungc539dbb2022-12-08 07:45:36 +00005526TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5527 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5528
5529 // Create a couple of windows
5530 sp<FakeWindowHandle> firstWindow =
5531 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5532 ADISPLAY_ID_DEFAULT);
5533 firstWindow->setDupTouchToWallpaper(true);
5534 sp<FakeWindowHandle> secondWindow =
5535 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5536 ADISPLAY_ID_DEFAULT);
5537 secondWindow->setDupTouchToWallpaper(true);
5538
5539 sp<FakeWindowHandle> wallpaper1 =
5540 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5541 wallpaper1->setIsWallpaper(true);
5542
5543 sp<FakeWindowHandle> wallpaper2 =
5544 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5545 wallpaper2->setIsWallpaper(true);
5546 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005547 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5548 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5549 {},
5550 0,
5551 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005552
5553 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005554 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5555 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005556
5557 // Only the first window should get the down event
5558 firstWindow->consumeMotionDown();
5559 secondWindow->assertNoEvents();
5560 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5561 wallpaper2->assertNoEvents();
5562
5563 // Transfer touch focus to the second window
5564 TransferFunction f = GetParam();
5565 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5566 ASSERT_TRUE(success);
5567
5568 // The first window gets cancel and the second gets down
5569 firstWindow->consumeMotionCancel();
5570 secondWindow->consumeMotionDown();
5571 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5572 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5573
5574 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005575 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5576 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005577 // The first window gets no events and the second gets up
5578 firstWindow->assertNoEvents();
5579 secondWindow->consumeMotionUp();
5580 wallpaper1->assertNoEvents();
5581 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5582}
5583
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005584// For the cases of single pointer touch and two pointers non-split touch, the api's
5585// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5586// for the case where there are multiple pointers split across several windows.
5587INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5588 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005589 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5590 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005591 return dispatcher->transferTouch(destChannelToken,
5592 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005593 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005594 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5595 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005596 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005597 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005598 }));
5599
Svet Ganov5d3bc372020-01-26 23:11:07 -08005600TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005601 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005602
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005603 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005604 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5605 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005606 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005607
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005608 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005609 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5610 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005611 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005612
5613 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005614 mDispatcher->onWindowInfosChanged(
5615 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005616
5617 PointF pointInFirst = {300, 200};
5618 PointF pointInSecond = {300, 600};
5619
5620 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005621 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5622 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5623 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005624 // Only the first window should get the down event
5625 firstWindow->consumeMotionDown();
5626 secondWindow->assertNoEvents();
5627
5628 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005629 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5630 ADISPLAY_ID_DEFAULT,
5631 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005632 // The first window gets a move and the second a down
5633 firstWindow->consumeMotionMove();
5634 secondWindow->consumeMotionDown();
5635
5636 // Transfer touch focus to the second window
5637 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5638 // The first window gets cancel and the new gets pointer down (it already saw down)
5639 firstWindow->consumeMotionCancel();
5640 secondWindow->consumeMotionPointerDown(1);
5641
5642 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005643 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5644 ADISPLAY_ID_DEFAULT,
5645 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005646 // The first window gets nothing and the second gets pointer up
5647 firstWindow->assertNoEvents();
5648 secondWindow->consumeMotionPointerUp(1);
5649
5650 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005651 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5652 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005653 // The first window gets nothing and the second gets up
5654 firstWindow->assertNoEvents();
5655 secondWindow->consumeMotionUp();
5656}
5657
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005658// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5659// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5660// touch is not supported, so the touch should continue on those windows and the transferred-to
5661// window should get nothing.
5662TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5663 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5664
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005665 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005666 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5667 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005668 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005669
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005670 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005671 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5672 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005673 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005674
5675 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005676 mDispatcher->onWindowInfosChanged(
5677 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005678
5679 PointF pointInFirst = {300, 200};
5680 PointF pointInSecond = {300, 600};
5681
5682 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005683 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5684 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5685 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005686 // Only the first window should get the down event
5687 firstWindow->consumeMotionDown();
5688 secondWindow->assertNoEvents();
5689
5690 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005691 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5692 ADISPLAY_ID_DEFAULT,
5693 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005694 // The first window gets a move and the second a down
5695 firstWindow->consumeMotionMove();
5696 secondWindow->consumeMotionDown();
5697
5698 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005699 const bool transferred =
5700 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005701 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5702 ASSERT_FALSE(transferred);
5703 firstWindow->assertNoEvents();
5704 secondWindow->assertNoEvents();
5705
5706 // The rest of the dispatch should proceed as normal
5707 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005708 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5709 ADISPLAY_ID_DEFAULT,
5710 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005711 // The first window gets MOVE and the second gets pointer up
5712 firstWindow->consumeMotionMove();
5713 secondWindow->consumeMotionUp();
5714
5715 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005716 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5717 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005718 // The first window gets nothing and the second gets up
5719 firstWindow->consumeMotionUp();
5720 secondWindow->assertNoEvents();
5721}
5722
Arthur Hungabbb9d82021-09-01 14:52:30 +00005723// This case will create two windows and one mirrored window on the default display and mirror
5724// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5725// the windows info of second display before default display.
5726TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5727 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5728 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005729 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005730 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005731 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005732 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005733 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005734
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005735 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005736 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005737
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005738 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005739 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005740
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005741 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005742 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005743
5744 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005745 mDispatcher->onWindowInfosChanged(
5746 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5747 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5748 *secondWindowInPrimary->getInfo()},
5749 {},
5750 0,
5751 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005752
5753 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005754 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005755 {50, 50}))
5756 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5757
5758 // Window should receive motion event.
5759 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5760
5761 // Transfer touch focus
5762 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5763 secondWindowInPrimary->getToken()));
5764 // The first window gets cancel.
5765 firstWindowInPrimary->consumeMotionCancel();
5766 secondWindowInPrimary->consumeMotionDown();
5767
5768 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005769 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005770 ADISPLAY_ID_DEFAULT, {150, 50}))
5771 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5772 firstWindowInPrimary->assertNoEvents();
5773 secondWindowInPrimary->consumeMotionMove();
5774
5775 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005776 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005777 {150, 50}))
5778 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5779 firstWindowInPrimary->assertNoEvents();
5780 secondWindowInPrimary->consumeMotionUp();
5781}
5782
5783// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5784// 'transferTouch' api.
5785TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5786 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5787 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005788 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005789 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005790 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005791 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005792 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005793
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005794 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005795 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005796
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005797 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005798 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005799
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005800 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005801 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005802
5803 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005804 mDispatcher->onWindowInfosChanged(
5805 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5806 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5807 *secondWindowInPrimary->getInfo()},
5808 {},
5809 0,
5810 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005811
5812 // Touch on second display.
5813 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005814 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5815 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005816 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5817
5818 // Window should receive motion event.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005819 firstWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005820
5821 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005822 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005823
5824 // The first window gets cancel.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005825 firstWindowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
5826 secondWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005827
5828 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005829 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005830 SECOND_DISPLAY_ID, {150, 50}))
5831 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005832 firstWindowInSecondary->assertNoEvents();
5833 secondWindowInSecondary->consumeMotionMove(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005834
5835 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005836 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005837 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005838 firstWindowInSecondary->assertNoEvents();
5839 secondWindowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005840}
5841
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005842TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005843 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005844 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5845 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005846
Vishnu Nair47074b82020-08-14 11:54:47 -07005847 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005848 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005849 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005850
5851 window->consumeFocusEvent(true);
5852
Prabir Pradhan678438e2023-04-13 19:32:51 +00005853 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005854
5855 // Window should receive key down event.
5856 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005857
5858 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005859 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005860 mFakePolicy->assertUserActivityPoked();
5861}
5862
5863TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5864 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5865 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5866 "Fake Window", ADISPLAY_ID_DEFAULT);
5867
5868 window->setDisableUserActivity(true);
5869 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005870 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005871 setFocusedWindow(window);
5872
5873 window->consumeFocusEvent(true);
5874
5875 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5876
5877 // Window should receive key down event.
5878 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5879
5880 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005881 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005882 mFakePolicy->assertUserActivityNotPoked();
5883}
5884
5885TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5886 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5887 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5888 "Fake Window", ADISPLAY_ID_DEFAULT);
5889
5890 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005891 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005892 setFocusedWindow(window);
5893
5894 window->consumeFocusEvent(true);
5895
5896 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5897 mDispatcher->waitForIdle();
5898
5899 // System key is not passed down
5900 window->assertNoEvents();
5901
5902 // Should have poked user activity
5903 mFakePolicy->assertUserActivityPoked();
5904}
5905
5906TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5907 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5908 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5909 "Fake Window", ADISPLAY_ID_DEFAULT);
5910
5911 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005912 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005913 setFocusedWindow(window);
5914
5915 window->consumeFocusEvent(true);
5916
5917 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5918 mDispatcher->waitForIdle();
5919
5920 // System key is not passed down
5921 window->assertNoEvents();
5922
5923 // Should have poked user activity
5924 mFakePolicy->assertUserActivityPoked();
5925}
5926
5927TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5928 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5929 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5930 "Fake Window", ADISPLAY_ID_DEFAULT);
5931
5932 window->setDisableUserActivity(true);
5933 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005934 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005935 setFocusedWindow(window);
5936
5937 window->consumeFocusEvent(true);
5938
5939 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5940 mDispatcher->waitForIdle();
5941
5942 // System key is not passed down
5943 window->assertNoEvents();
5944
5945 // Should have poked user activity
5946 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005947}
5948
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005949TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5950 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5951 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5952 "Fake Window", ADISPLAY_ID_DEFAULT);
5953
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005954 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005955
5956 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005957 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005958 ADISPLAY_ID_DEFAULT, {100, 100}))
5959 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5960
5961 window->consumeMotionEvent(
5962 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5963
5964 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005965 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005966 mFakePolicy->assertUserActivityPoked();
5967}
5968
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005969TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005970 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005971 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5972 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005973
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005974 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005975
Prabir Pradhan678438e2023-04-13 19:32:51 +00005976 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005977 mDispatcher->waitForIdle();
5978
5979 window->assertNoEvents();
5980}
5981
5982// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5983TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005984 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005985 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5986 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005987
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005988 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005989
5990 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005991 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005992 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005993 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5994 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005995
5996 // Window should receive only the motion event
5997 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5998 window->assertNoEvents(); // Key event or focus event will not be received
5999}
6000
arthurhungea3f4fc2020-12-21 23:18:53 +08006001TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
6002 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6003
arthurhungea3f4fc2020-12-21 23:18:53 +08006004 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006005 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
6006 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08006007 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08006008
arthurhungea3f4fc2020-12-21 23:18:53 +08006009 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006010 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
6011 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08006012 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08006013
6014 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006015 mDispatcher->onWindowInfosChanged(
6016 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08006017
6018 PointF pointInFirst = {300, 200};
6019 PointF pointInSecond = {300, 600};
6020
6021 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006022 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6023 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6024 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08006025 // Only the first window should get the down event
6026 firstWindow->consumeMotionDown();
6027 secondWindow->assertNoEvents();
6028
6029 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006030 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6031 ADISPLAY_ID_DEFAULT,
6032 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08006033 // The first window gets a move and the second a down
6034 firstWindow->consumeMotionMove();
6035 secondWindow->consumeMotionDown();
6036
6037 // Send pointer cancel to the second window
6038 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006039 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08006040 {pointInFirst, pointInSecond});
6041 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00006042 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08006043 // The first window gets move and the second gets cancel.
6044 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
6045 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
6046
6047 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00006048 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6049 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08006050 // The first window gets up and the second gets nothing.
6051 firstWindow->consumeMotionUp();
6052 secondWindow->assertNoEvents();
6053}
6054
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006055TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
6056 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6057
6058 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006059 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006060 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006061 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
6062 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
6063 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
6064
Harry Cutts33476232023-01-30 19:57:29 +00006065 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006066 window->assertNoEvents();
6067 mDispatcher->waitForIdle();
6068}
6069
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006070using InputDispatcherMonitorTest = InputDispatcherTest;
6071
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006072/**
6073 * Two entities that receive touch: A window, and a global monitor.
6074 * The touch goes to the window, and then the window disappears.
6075 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
6076 * for the monitor, as well.
6077 * 1. foregroundWindow
6078 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
6079 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006080TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006081 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6082 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006083 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006084
Prabir Pradhanfb549072023-10-05 19:17:36 +00006085 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006086
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006087 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006088 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006089 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006090 {100, 200}))
6091 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6092
6093 // Both the foreground window and the global monitor should receive the touch down
6094 window->consumeMotionDown();
6095 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6096
6097 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006098 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006099 ADISPLAY_ID_DEFAULT, {110, 200}))
6100 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6101
6102 window->consumeMotionMove();
6103 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6104
6105 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006106 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006107 window->consumeMotionCancel();
6108 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
6109
6110 // If more events come in, there will be no more foreground window to send them to. This will
6111 // cause a cancel for the monitor, as well.
6112 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006113 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006114 ADISPLAY_ID_DEFAULT, {120, 200}))
6115 << "Injection should fail because the window was removed";
6116 window->assertNoEvents();
6117 // Global monitor now gets the cancel
6118 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6119}
6120
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006121TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07006122 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006123 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6124 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006125 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006126
Prabir Pradhanfb549072023-10-05 19:17:36 +00006127 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006128
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006129 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006130 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006131 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00006132 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006133 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006134}
6135
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006136TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00006137 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006138
Chris Yea209fde2020-07-22 13:54:51 -07006139 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006140 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6141 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006142 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006143
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006144 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006145 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006146 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08006147 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006148 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006149
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006150 // Pilfer pointers from the monitor.
6151 // This should not do anything and the window should continue to receive events.
6152 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00006153
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006154 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006155 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006156 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006157 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006158
6159 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6160 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006161}
6162
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006163TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07006164 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006165 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6166 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006167 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07006168 window->setWindowOffset(20, 40);
6169 window->setWindowTransform(0, 1, -1, 0);
6170
Prabir Pradhanfb549072023-10-05 19:17:36 +00006171 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07006172
6173 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006174 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07006175 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6176 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006177 std::unique_ptr<MotionEvent> event = monitor.consumeMotion();
6178 ASSERT_NE(nullptr, event);
Evan Rosky84f07f02021-04-16 10:42:42 -07006179 // Even though window has transform, gesture monitor must not.
6180 ASSERT_EQ(ui::Transform(), event->getTransform());
6181}
6182
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006183TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00006184 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00006185 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00006186
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006187 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006188 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006189 << "Injection should fail if there is a monitor, but no touchable window";
6190 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00006191}
6192
Linnan Lid8150952024-01-26 18:07:17 +00006193/**
6194 * Two displays
6195 * The first monitor has a foreground window, a monitor
6196 * The second window has only one monitor.
6197 * We first inject a Down event into the first display, this injection should succeed and both
6198 * the foreground window and monitor should receive a down event, then inject a Down event into
6199 * the second display as well, this injection should fail, at this point, the first display
6200 * window and monitor should not receive a cancel or any other event.
6201 * Continue to inject Move and UP events to the first display, the events should be received
6202 * normally by the foreground window and monitor.
6203 */
6204TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCanceledWhenAnotherEmptyDisplayReceiveEvents) {
6205 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6206 sp<FakeWindowHandle> window =
6207 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6208
6209 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6210 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
6211
6212 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6213 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6214 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6215 {100, 200}))
6216 << "The down event injected into the first display should succeed";
6217
6218 window->consumeMotionDown();
6219 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006220
6221 ASSERT_EQ(InputEventInjectionResult::FAILED,
6222 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6223 {100, 200}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006224 << "The down event injected into the second display should fail since there's no "
6225 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006226
6227 // Continue to inject event to first display.
6228 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6229 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6230 ADISPLAY_ID_DEFAULT, {110, 220}))
6231 << "The move event injected into the first display should succeed";
6232
6233 window->consumeMotionMove();
6234 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006235
6236 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6237 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6238 {110, 220}))
6239 << "The up event injected into the first display should succeed";
6240
6241 window->consumeMotionUp();
6242 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006243
6244 window->assertNoEvents();
6245 monitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00006246 secondMonitor.assertNoEvents();
6247}
6248
6249/**
6250 * Two displays
6251 * There is a monitor and foreground window on each display.
6252 * First, we inject down events into each of the two displays, at this point, the foreground windows
6253 * and monitors on both displays should receive down events.
6254 * At this point, the foreground window of the second display goes away, the gone window should
6255 * receive the cancel event, and the other windows and monitors should not receive any events.
6256 * Inject a move event into the second display. At this point, the injection should fail because
6257 * the second display no longer has a foreground window. At this point, the monitor on the second
6258 * display should receive a cancel event, and any windows or monitors on the first display should
6259 * not receive any events, and any subsequent injection of events into the second display should
6260 * also fail.
6261 * Continue to inject events into the first display, and the events should all be injected
6262 * successfully and received normally.
6263 */
6264TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCancelWhenAnotherDisplayMonitorTouchCanceled) {
6265 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6266 sp<FakeWindowHandle> window =
6267 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6268 sp<FakeWindowHandle> secondWindow =
6269 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondForeground",
6270 SECOND_DISPLAY_ID);
6271
6272 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6273 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
6274
6275 // There is a foreground window on both displays.
6276 mDispatcher->onWindowInfosChanged({{*window->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
6277 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6278 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6279 {100, 200}))
6280 << "The down event injected into the first display should succeed";
6281
6282 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6283 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006284
6285 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6286 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6287 {100, 200}))
6288 << "The down event injected into the second display should succeed";
6289
Linnan Lid8150952024-01-26 18:07:17 +00006290 secondWindow->consumeMotionDown(SECOND_DISPLAY_ID);
6291 secondMonitor.consumeMotionDown(SECOND_DISPLAY_ID);
6292
6293 // Now second window is gone away.
6294 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6295
6296 // The gone window should receive a cancel, and the monitor on the second display should not
6297 // receive any events.
Linnan Lid8150952024-01-26 18:07:17 +00006298 secondWindow->consumeMotionCancel(SECOND_DISPLAY_ID);
6299 secondMonitor.assertNoEvents();
6300
6301 ASSERT_EQ(InputEventInjectionResult::FAILED,
6302 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6303 SECOND_DISPLAY_ID, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006304 << "The move event injected into the second display should fail because there's no "
6305 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006306 // Now the monitor on the second display should receive a cancel event.
6307 secondMonitor.consumeMotionCancel(SECOND_DISPLAY_ID);
Linnan Lid8150952024-01-26 18:07:17 +00006308
6309 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6310 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6311 ADISPLAY_ID_DEFAULT, {110, 200}))
6312 << "The move event injected into the first display should succeed";
6313
6314 window->consumeMotionMove();
6315 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006316
6317 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006318 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6319 {110, 220}))
6320 << "The up event injected into the second display should fail because there's no "
6321 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006322
6323 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6324 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6325 {110, 220}))
6326 << "The up event injected into the first display should succeed";
6327
6328 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6329 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006330
Linnan Lid8150952024-01-26 18:07:17 +00006331 window->assertNoEvents();
6332 monitor.assertNoEvents();
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006333 secondWindow->assertNoEvents();
6334 secondMonitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00006335}
6336
6337/**
6338 * One display with transform
6339 * There is a foreground window and a monitor on the display
6340 * Inject down event and move event sequentially, the foreground window and monitor can receive down
6341 * event and move event, then let the foreground window go away, the foreground window receives
6342 * cancel event, inject move event again, the monitor receives cancel event, all the events received
6343 * by the monitor should be with the same transform as the display
6344 */
6345TEST_F(InputDispatcherMonitorTest, MonitorTouchCancelEventWithDisplayTransform) {
6346 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6347 sp<FakeWindowHandle> window =
6348 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6349 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6350
6351 ui::Transform transform;
6352 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6353
6354 gui::DisplayInfo displayInfo;
6355 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6356 displayInfo.transform = transform;
6357
6358 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
6359
6360 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6361 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6362 {100, 200}))
6363 << "The down event injected should succeed";
6364
6365 window->consumeMotionDown();
6366 std::unique_ptr<MotionEvent> downMotionEvent = monitor.consumeMotion();
6367 EXPECT_EQ(transform, downMotionEvent->getTransform());
6368 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, downMotionEvent->getAction());
6369
6370 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6371 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6372 ADISPLAY_ID_DEFAULT, {110, 220}))
6373 << "The move event injected should succeed";
6374
6375 window->consumeMotionMove();
6376 std::unique_ptr<MotionEvent> moveMotionEvent = monitor.consumeMotion();
6377 EXPECT_EQ(transform, moveMotionEvent->getTransform());
6378 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, moveMotionEvent->getAction());
6379
6380 // Let foreground window gone
6381 mDispatcher->onWindowInfosChanged({{}, {displayInfo}, 0, 0});
6382
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006383 // Foreground window should receive a cancel event, but not the monitor.
Linnan Lid8150952024-01-26 18:07:17 +00006384 window->consumeMotionCancel();
Linnan Lid8150952024-01-26 18:07:17 +00006385
6386 ASSERT_EQ(InputEventInjectionResult::FAILED,
6387 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6388 ADISPLAY_ID_DEFAULT, {110, 220}))
6389 << "The move event injected should failed";
6390 // Now foreground should not receive any events, but monitor should receive a cancel event
6391 // with transform that same as display's display.
Linnan Lid8150952024-01-26 18:07:17 +00006392 std::unique_ptr<MotionEvent> cancelMotionEvent = monitor.consumeMotion();
6393 EXPECT_EQ(transform, cancelMotionEvent->getTransform());
6394 EXPECT_EQ(ADISPLAY_ID_DEFAULT, cancelMotionEvent->getDisplayId());
6395 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, cancelMotionEvent->getAction());
6396
6397 // Other event inject to this display should fail.
6398 ASSERT_EQ(InputEventInjectionResult::FAILED,
6399 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6400 ADISPLAY_ID_DEFAULT, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006401 << "The up event injected should fail because the touched window was removed";
Linnan Lid8150952024-01-26 18:07:17 +00006402 window->assertNoEvents();
6403 monitor.assertNoEvents();
6404}
6405
chaviw81e2bb92019-12-18 15:03:51 -08006406TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006407 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006408 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6409 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08006410
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006411 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08006412
6413 NotifyMotionArgs motionArgs =
6414 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6415 ADISPLAY_ID_DEFAULT);
6416
Prabir Pradhan678438e2023-04-13 19:32:51 +00006417 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08006418 // Window should receive motion down event.
6419 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6420
6421 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08006422 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08006423 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6424 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
6425 motionArgs.pointerCoords[0].getX() - 10);
6426
Prabir Pradhan678438e2023-04-13 19:32:51 +00006427 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006428 window->consumeMotionMove(ADISPLAY_ID_DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08006429}
6430
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006431/**
6432 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
6433 * the device default right away. In the test scenario, we check both the default value,
6434 * and the action of enabling / disabling.
6435 */
6436TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07006437 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006438 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6439 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08006440 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006441
6442 // Set focused application.
6443 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006444 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006445
6446 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006447 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006448 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006449 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006450
6451 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006452 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006453 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006454 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006455
6456 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006457 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006458 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006459 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07006460 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006461 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006462 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006463 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006464
6465 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006466 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006467 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006468 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006469
6470 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006471 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006472 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006473 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07006474 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006475 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006476 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006477 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006478
6479 window->assertNoEvents();
6480}
6481
Gang Wange9087892020-01-07 12:17:14 -05006482TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006483 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006484 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6485 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05006486
6487 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006488 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05006489
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006490 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006491 setFocusedWindow(window);
6492
Harry Cutts33476232023-01-30 19:57:29 +00006493 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05006494
Prabir Pradhan678438e2023-04-13 19:32:51 +00006495 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
6496 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05006497
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006498 std::unique_ptr<KeyEvent> event = window->consumeKey();
6499 ASSERT_NE(event, nullptr);
6500 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Gang Wange9087892020-01-07 12:17:14 -05006501 ASSERT_NE(verified, nullptr);
6502 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
6503
6504 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
6505 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
6506 ASSERT_EQ(keyArgs.source, verified->source);
6507 ASSERT_EQ(keyArgs.displayId, verified->displayId);
6508
6509 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
6510
6511 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05006512 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006513 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05006514 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
6515 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
6516 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
6517 ASSERT_EQ(0, verifiedKey.repeatCount);
6518}
6519
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006520TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006521 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006522 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6523 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006524
6525 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6526
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006527 ui::Transform transform;
6528 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6529
6530 gui::DisplayInfo displayInfo;
6531 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6532 displayInfo.transform = transform;
6533
Patrick Williamsd828f302023-04-28 17:52:08 -05006534 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006535
Prabir Pradhan678438e2023-04-13 19:32:51 +00006536 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006537 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6538 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006539 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006540
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006541 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
6542 ASSERT_NE(nullptr, event);
6543 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006544 ASSERT_NE(verified, nullptr);
6545 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
6546
6547 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
6548 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
6549 EXPECT_EQ(motionArgs.source, verified->source);
6550 EXPECT_EQ(motionArgs.displayId, verified->displayId);
6551
6552 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
6553
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006554 const vec2 rawXY =
6555 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
6556 motionArgs.pointerCoords[0].getXYValue());
6557 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
6558 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006559 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006560 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006561 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006562 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
6563 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
6564}
6565
chaviw09c8d2d2020-08-24 15:48:26 -07006566/**
6567 * Ensure that separate calls to sign the same data are generating the same key.
6568 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
6569 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
6570 * tests.
6571 */
6572TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
6573 KeyEvent event = getTestKeyEvent();
6574 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6575
6576 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
6577 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
6578 ASSERT_EQ(hmac1, hmac2);
6579}
6580
6581/**
6582 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6583 */
6584TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6585 KeyEvent event = getTestKeyEvent();
6586 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6587 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6588
6589 verifiedEvent.deviceId += 1;
6590 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6591
6592 verifiedEvent.source += 1;
6593 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6594
6595 verifiedEvent.eventTimeNanos += 1;
6596 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6597
6598 verifiedEvent.displayId += 1;
6599 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6600
6601 verifiedEvent.action += 1;
6602 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6603
6604 verifiedEvent.downTimeNanos += 1;
6605 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6606
6607 verifiedEvent.flags += 1;
6608 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6609
6610 verifiedEvent.keyCode += 1;
6611 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6612
6613 verifiedEvent.scanCode += 1;
6614 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6615
6616 verifiedEvent.metaState += 1;
6617 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6618
6619 verifiedEvent.repeatCount += 1;
6620 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6621}
6622
Vishnu Nair958da932020-08-21 17:12:37 -07006623TEST_F(InputDispatcherTest, SetFocusedWindow) {
6624 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6625 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006626 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006627 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006628 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006629 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6630
6631 // Top window is also focusable but is not granted focus.
6632 windowTop->setFocusable(true);
6633 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006634 mDispatcher->onWindowInfosChanged(
6635 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006636 setFocusedWindow(windowSecond);
6637
6638 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006639 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006640 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006641
6642 // Focused window should receive event.
6643 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6644 windowTop->assertNoEvents();
6645}
6646
6647TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
6648 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6649 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006650 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006651 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6652
6653 window->setFocusable(true);
6654 // Release channel for window is no longer valid.
6655 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006656 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006657 setFocusedWindow(window);
6658
6659 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006660 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006661
6662 // window channel is invalid, so it should not receive any input event.
6663 window->assertNoEvents();
6664}
6665
6666TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
6667 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6668 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006669 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006670 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006671 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6672
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006673 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006674 setFocusedWindow(window);
6675
6676 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006677 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006678
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006679 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006680 window->assertNoEvents();
6681}
6682
6683TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6684 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6685 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006686 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006687 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006688 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006689 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6690
6691 windowTop->setFocusable(true);
6692 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006693 mDispatcher->onWindowInfosChanged(
6694 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006695 setFocusedWindow(windowTop);
6696 windowTop->consumeFocusEvent(true);
6697
Chavi Weingarten847e8512023-03-29 00:26:09 +00006698 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006699 mDispatcher->onWindowInfosChanged(
6700 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006701 windowSecond->consumeFocusEvent(true);
6702 windowTop->consumeFocusEvent(false);
6703
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006704 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006705 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006706
6707 // Focused window should receive event.
6708 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6709}
6710
Chavi Weingarten847e8512023-03-29 00:26:09 +00006711TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006712 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6713 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006714 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006715 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006716 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006717 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6718
6719 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006720 windowSecond->setFocusable(false);
6721 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006722 mDispatcher->onWindowInfosChanged(
6723 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006724 setFocusedWindow(windowTop);
6725 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006726
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006727 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006728 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006729
6730 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006731 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006732 windowSecond->assertNoEvents();
6733}
6734
6735TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6736 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6737 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006738 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006739 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006740 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6741 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006742 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6743
6744 window->setFocusable(true);
6745 previousFocusedWindow->setFocusable(true);
6746 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006747 mDispatcher->onWindowInfosChanged(
6748 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006749 setFocusedWindow(previousFocusedWindow);
6750 previousFocusedWindow->consumeFocusEvent(true);
6751
6752 // Requesting focus on invisible window takes focus from currently focused window.
6753 setFocusedWindow(window);
6754 previousFocusedWindow->consumeFocusEvent(false);
6755
6756 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006757 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006758 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6759 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006760
6761 // Window does not get focus event or key down.
6762 window->assertNoEvents();
6763
6764 // Window becomes visible.
6765 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006766 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006767
6768 // Window receives focus event.
6769 window->consumeFocusEvent(true);
6770 // Focused window receives key down.
6771 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6772}
6773
Vishnu Nair599f1412021-06-21 10:39:58 -07006774TEST_F(InputDispatcherTest, DisplayRemoved) {
6775 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6776 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006777 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006778 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6779
6780 // window is granted focus.
6781 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006782 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006783 setFocusedWindow(window);
6784 window->consumeFocusEvent(true);
6785
6786 // When a display is removed window loses focus.
6787 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6788 window->consumeFocusEvent(false);
6789}
6790
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006791/**
6792 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6793 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6794 * of the 'slipperyEnterWindow'.
6795 *
6796 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6797 * a way so that the touched location is no longer covered by the top window.
6798 *
6799 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6800 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6801 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6802 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6803 * with ACTION_DOWN).
6804 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6805 * window moved itself away from the touched location and had Flag::SLIPPERY.
6806 *
6807 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6808 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6809 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6810 *
6811 * In this test, we ensure that the event received by the bottom window has
6812 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6813 */
6814TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006815 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006816 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006817
6818 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6819 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6820
6821 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006822 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006823 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006824 // Make sure this one overlaps the bottom window
6825 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6826 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6827 // one. Windows with the same owner are not considered to be occluding each other.
6828 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6829
6830 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006831 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006832 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6833
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006834 mDispatcher->onWindowInfosChanged(
6835 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006836
6837 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006838 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6839 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6840 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006841 slipperyExitWindow->consumeMotionDown();
6842 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006843 mDispatcher->onWindowInfosChanged(
6844 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006845
Prabir Pradhan678438e2023-04-13 19:32:51 +00006846 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6847 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6848 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006849
6850 slipperyExitWindow->consumeMotionCancel();
6851
6852 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6853 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6854}
6855
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006856/**
6857 * Two windows, one on the left and another on the right. The left window is slippery. The right
6858 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6859 * touch moves from the left window into the right window, the gesture should continue to go to the
6860 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6861 * reproduces a crash.
6862 */
6863TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6864 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6865
6866 sp<FakeWindowHandle> leftSlipperyWindow =
6867 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6868 leftSlipperyWindow->setSlippery(true);
6869 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6870
6871 sp<FakeWindowHandle> rightDropTouchesWindow =
6872 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6873 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6874 rightDropTouchesWindow->setDropInput(true);
6875
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006876 mDispatcher->onWindowInfosChanged(
6877 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006878
6879 // Start touch in the left window
6880 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6881 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6882 .build());
6883 leftSlipperyWindow->consumeMotionDown();
6884
6885 // And move it into the right window
6886 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6887 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6888 .build());
6889
6890 // Since the right window isn't eligible to receive input, touch does not slip.
6891 // The left window continues to receive the gesture.
6892 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6893 rightDropTouchesWindow->assertNoEvents();
6894}
6895
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006896/**
6897 * A single window is on screen first. Touch is injected into that window. Next, a second window
6898 * appears. Since the first window is slippery, touch will move from the first window to the second.
6899 */
6900TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6901 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6902 sp<FakeWindowHandle> originalWindow =
6903 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6904 originalWindow->setFrame(Rect(0, 0, 200, 200));
6905 originalWindow->setSlippery(true);
6906
6907 sp<FakeWindowHandle> appearingWindow =
6908 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6909 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6910
6911 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6912
6913 // Touch down on the original window
6914 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6915 injectMotionEvent(*mDispatcher,
6916 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6917 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6918 .build()));
6919 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6920
6921 // Now, a new window appears. This could be, for example, a notification shade that appears
6922 // after user starts to drag down on the launcher window.
6923 mDispatcher->onWindowInfosChanged(
6924 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6925 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6926 injectMotionEvent(*mDispatcher,
6927 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6928 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6929 .build()));
6930 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6931 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6932 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6933 injectMotionEvent(*mDispatcher,
6934 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6935 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6936 .build()));
6937 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6938
6939 originalWindow->assertNoEvents();
6940 appearingWindow->assertNoEvents();
6941}
6942
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006943TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006944 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006945 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6946
6947 sp<FakeWindowHandle> leftWindow =
6948 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6949 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006950 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006951
6952 sp<FakeWindowHandle> rightSpy =
6953 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6954 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006955 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006956 rightSpy->setSpy(true);
6957 rightSpy->setTrustedOverlay(true);
6958
6959 sp<FakeWindowHandle> rightWindow =
6960 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6961 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006962 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006963
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006964 mDispatcher->onWindowInfosChanged(
6965 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006966
6967 // Touch in the left window
6968 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6969 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6970 .build());
6971 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6972 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006973 ASSERT_NO_FATAL_FAILURE(
6974 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006975
6976 // Touch another finger over the right windows
6977 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6978 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6979 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6980 .build());
6981 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6982 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6983 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6984 mDispatcher->waitForIdle();
6985 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006986 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6987 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006988
6989 // Release finger over left window. The UP actions are not treated as device interaction.
6990 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6991 // is part of the UP action, we do not treat this as device interaction.
6992 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6993 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6994 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6995 .build());
6996 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6997 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6998 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6999 mDispatcher->waitForIdle();
7000 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7001
7002 // Move remaining finger
7003 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7004 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7005 .build());
7006 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
7007 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
7008 mDispatcher->waitForIdle();
7009 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007010 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007011
7012 // Release all fingers
7013 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7014 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7015 .build());
7016 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
7017 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
7018 mDispatcher->waitForIdle();
7019 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7020}
7021
7022TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
7023 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7024
7025 sp<FakeWindowHandle> window =
7026 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
7027 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007028 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007029
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007030 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007031 setFocusedWindow(window);
7032 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
7033
7034 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
7035 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
7036 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007037 ASSERT_NO_FATAL_FAILURE(
7038 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007039
7040 // The UP actions are not treated as device interaction.
7041 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
7042 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
7043 mDispatcher->waitForIdle();
7044 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7045}
7046
Prabir Pradhan5893d362023-11-17 04:30:40 +00007047TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
7048 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7049
7050 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
7051 ADISPLAY_ID_DEFAULT);
7052 left->setFrame(Rect(0, 0, 100, 100));
7053 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
7054 "Right Window", ADISPLAY_ID_DEFAULT);
7055 right->setFrame(Rect(100, 0, 200, 100));
7056 sp<FakeWindowHandle> spy =
7057 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
7058 spy->setFrame(Rect(0, 0, 200, 100));
7059 spy->setTrustedOverlay(true);
7060 spy->setSpy(true);
7061
7062 mDispatcher->onWindowInfosChanged(
7063 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
7064
7065 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
7066 NotifyMotionArgs notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
7067 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
7068 mDispatcher->notifyMotion(notifyArgs);
7069
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007070 std::unique_ptr<MotionEvent> leftEnter = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00007071 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
7072 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007073 ASSERT_NE(nullptr, leftEnter);
Prabir Pradhan5893d362023-11-17 04:30:40 +00007074 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
7075 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007076 Not(WithEventId(leftEnter->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00007077 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
7078
7079 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
7080 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
7081 {PointF{150, 50}});
7082 mDispatcher->notifyMotion(notifyArgs);
7083
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007084 std::unique_ptr<MotionEvent> leftExit = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00007085 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
7086 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007087 ASSERT_NE(nullptr, leftExit);
Prabir Pradhan5893d362023-11-17 04:30:40 +00007088 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
7089 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007090 Not(WithEventId(leftExit->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00007091 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
7092
7093 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
7094}
7095
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00007096class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
7097protected:
7098 std::shared_ptr<FakeApplicationHandle> mApp;
7099 sp<FakeWindowHandle> mWindow;
7100
7101 virtual void SetUp() override {
7102 InputDispatcherTest::SetUp();
7103
7104 mApp = std::make_shared<FakeApplicationHandle>();
7105
7106 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
7107 mWindow->setFrame(Rect(0, 0, 100, 100));
7108
7109 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
7110 setFocusedWindow(mWindow);
7111 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
7112 }
7113
7114 void setFallback(int32_t keycode) {
7115 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
7116 return KeyEventBuilder(event).keyCode(keycode).build();
7117 });
7118 }
7119
7120 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007121 std::unique_ptr<KeyEvent> event = mWindow->consumeKey(handled);
7122 ASSERT_NE(nullptr, event);
7123 ASSERT_THAT(*event, matcher);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00007124 }
7125};
7126
7127TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
7128 mDispatcher->notifyKey(
7129 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7130 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
7131 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7132}
7133
7134TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
7135 mDispatcher->notifyKey(
7136 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7137 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
7138 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7139}
7140
7141TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
7142 mDispatcher->notifyKey(
7143 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7144
7145 // Do not handle this key event.
7146 consumeKey(/*handled=*/false,
7147 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7148 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7149
7150 // Since the policy did not request any fallback to be generated, ensure there are no events.
7151 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7152}
7153
7154TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
7155 setFallback(AKEYCODE_B);
7156 mDispatcher->notifyKey(
7157 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7158
7159 // Do not handle this key event.
7160 consumeKey(/*handled=*/false,
7161 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7162
7163 // Since the key was not handled, ensure the fallback event was dispatched instead.
7164 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7165 consumeKey(/*handled=*/true,
7166 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7167 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7168
7169 // Release the original key, and ensure the fallback key is also released.
7170 mDispatcher->notifyKey(
7171 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7172 consumeKey(/*handled=*/false,
7173 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7174 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7175 consumeKey(/*handled=*/true,
7176 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7177 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7178
7179 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7180 mWindow->assertNoEvents();
7181}
7182
7183TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
7184 setFallback(AKEYCODE_B);
7185 mDispatcher->notifyKey(
7186 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7187
7188 // Do not handle this key event, but handle the fallback.
7189 consumeKey(/*handled=*/false,
7190 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7191 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7192 consumeKey(/*handled=*/true,
7193 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7194 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7195
7196 // Release the original key, and ensure the fallback key is also released.
7197 mDispatcher->notifyKey(
7198 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7199 // But this time, the app handles the original key.
7200 consumeKey(/*handled=*/true,
7201 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7202 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7203 // Ensure the fallback key is canceled.
7204 consumeKey(/*handled=*/true,
7205 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7206 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7207
7208 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7209 mWindow->assertNoEvents();
7210}
7211
7212TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
7213 setFallback(AKEYCODE_B);
7214 mDispatcher->notifyKey(
7215 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7216
7217 // Do not handle this key event.
7218 consumeKey(/*handled=*/false,
7219 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7220 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7221 // App does not handle the fallback either, so ensure another fallback is not generated.
7222 setFallback(AKEYCODE_C);
7223 consumeKey(/*handled=*/false,
7224 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7225 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7226
7227 // Release the original key, and ensure the fallback key is also released.
7228 setFallback(AKEYCODE_B);
7229 mDispatcher->notifyKey(
7230 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7231 consumeKey(/*handled=*/false,
7232 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7233 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7234 consumeKey(/*handled=*/false,
7235 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7236 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7237
7238 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7239 mWindow->assertNoEvents();
7240}
7241
7242TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
7243 setFallback(AKEYCODE_B);
7244 mDispatcher->notifyKey(
7245 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7246
7247 // Do not handle this key event, so fallback is generated.
7248 consumeKey(/*handled=*/false,
7249 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7250 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7251 consumeKey(/*handled=*/true,
7252 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7253 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7254
7255 // Release the original key, but assume the policy is misbehaving and it
7256 // generates an inconsistent fallback to the one from the DOWN event.
7257 setFallback(AKEYCODE_C);
7258 mDispatcher->notifyKey(
7259 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7260 consumeKey(/*handled=*/false,
7261 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7262 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7263 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
7264 consumeKey(/*handled=*/true,
7265 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7266 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7267
7268 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7269 mWindow->assertNoEvents();
7270}
7271
7272TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
7273 setFallback(AKEYCODE_B);
7274 mDispatcher->notifyKey(
7275 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7276
7277 // Do not handle this key event, so fallback is generated.
7278 consumeKey(/*handled=*/false,
7279 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7280 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7281 consumeKey(/*handled=*/true,
7282 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7283 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7284
7285 // The original key is canceled.
7286 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
7287 .keyCode(AKEYCODE_A)
7288 .addFlag(AKEY_EVENT_FLAG_CANCELED)
7289 .build());
7290 consumeKey(/*handled=*/false,
7291 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
7292 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7293 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7294 // Ensure the fallback key is also canceled due to the original key being canceled.
7295 consumeKey(/*handled=*/true,
7296 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7297 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7298
7299 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7300 mWindow->assertNoEvents();
7301}
7302
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00007303TEST_F(InputDispatcherFallbackKeyTest, InputChannelRemovedDuringPolicyCall) {
Prabir Pradhanb13da8f2024-01-09 23:10:13 +00007304 setFallback(AKEYCODE_B);
7305 mDispatcher->notifyKey(
7306 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7307
7308 // Do not handle this key event.
7309 consumeKey(/*handled=*/false,
7310 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7311 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7312 consumeKey(/*handled=*/true,
7313 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7314 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7315
7316 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
7317 // When the unhandled key is reported to the policy next, remove the input channel.
7318 mDispatcher->removeInputChannel(mWindow->getToken());
7319 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
7320 });
7321 // Release the original key, and let the app now handle the previously unhandled key.
7322 // This should result in the previously generated fallback key to be cancelled.
7323 // Since the policy was notified of the unhandled DOWN event earlier, it will also be notified
7324 // of the UP event for consistency. The Dispatcher calls into the policy from its own thread
7325 // without holding the lock, because it need to synchronously fetch the fallback key. While in
7326 // the policy call, we will now remove the input channel. Once the policy call returns, the
7327 // Dispatcher will no longer have a channel to send cancellation events to. Ensure this does
7328 // not cause any crashes.
7329 mDispatcher->notifyKey(
7330 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7331 consumeKey(/*handled=*/true,
7332 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7333 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7334}
7335
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00007336TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedDuringPolicyCall) {
7337 setFallback(AKEYCODE_B);
7338 mDispatcher->notifyKey(
7339 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7340
7341 // Do not handle this key event.
7342 consumeKey(/*handled=*/false,
7343 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7344 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7345 consumeKey(/*handled=*/true,
7346 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7347 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7348
7349 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
7350 // When the unhandled key is reported to the policy next, remove the window.
7351 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
7352 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
7353 });
7354 // Release the original key, which the app will not handle. When this unhandled key is reported
7355 // to the policy, the window will be removed.
7356 mDispatcher->notifyKey(
7357 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7358 consumeKey(/*handled=*/false,
7359 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7360 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7361
7362 // Since the window was removed, it loses focus, and the channel state will be reset.
7363 consumeKey(/*handled=*/true,
7364 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7365 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7366 mWindow->consumeFocusEvent(false);
7367 mWindow->assertNoEvents();
7368}
7369
7370TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedWhileAwaitingFinishedSignal) {
7371 setFallback(AKEYCODE_B);
7372 mDispatcher->notifyKey(
7373 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7374
7375 // Do not handle this key event.
7376 consumeKey(/*handled=*/false,
7377 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7378 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7379 const auto [seq, event] = mWindow->receiveEvent();
7380 ASSERT_TRUE(seq.has_value() && event != nullptr) << "Failed to receive fallback event";
7381 ASSERT_EQ(event->getType(), InputEventType::KEY);
7382 ASSERT_THAT(static_cast<const KeyEvent&>(*event),
7383 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7384 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7385
7386 // Remove the window now, which should generate a cancellations and make the window lose focus.
7387 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
7388 consumeKey(/*handled=*/true,
7389 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
7390 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7391 consumeKey(/*handled=*/true,
7392 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7393 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7394 mWindow->consumeFocusEvent(false);
7395
7396 // Finish the event by reporting it as handled.
7397 mWindow->finishEvent(*seq);
7398 mWindow->assertNoEvents();
7399}
7400
Garfield Tan1c7bc862020-01-28 13:24:04 -08007401class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
7402protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08007403 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
7404 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007405
Chris Yea209fde2020-07-22 13:54:51 -07007406 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007407 sp<FakeWindowHandle> mWindow;
7408
7409 virtual void SetUp() override {
Prabir Pradhandae52792023-12-15 07:36:40 +00007410 InputDispatcherTest::SetUp();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007411
Prabir Pradhandae52792023-12-15 07:36:40 +00007412 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007413 setUpWindow();
7414 }
7415
7416 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07007417 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007418 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007419
Vishnu Nair47074b82020-08-14 11:54:47 -07007420 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007421 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007422 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007423 mWindow->consumeFocusEvent(true);
7424 }
7425
Chris Ye2ad95392020-09-01 13:44:44 -07007426 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007427 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007428 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007429 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007430 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007431
7432 // Window should receive key down event.
7433 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7434 }
7435
7436 void expectKeyRepeatOnce(int32_t repeatCount) {
7437 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007438 mWindow->consumeKeyEvent(
7439 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007440 }
7441
Chris Ye2ad95392020-09-01 13:44:44 -07007442 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007443 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007444 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007445 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007446 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007447
7448 // Window should receive key down event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007449 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007450 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007451 }
7452};
7453
7454TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00007455 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007456 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7457 expectKeyRepeatOnce(repeatCount);
7458 }
7459}
7460
7461TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00007462 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007463 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7464 expectKeyRepeatOnce(repeatCount);
7465 }
Harry Cutts33476232023-01-30 19:57:29 +00007466 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007467 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08007468 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7469 expectKeyRepeatOnce(repeatCount);
7470 }
7471}
7472
7473TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007474 sendAndConsumeKeyDown(/*deviceId=*/1);
7475 expectKeyRepeatOnce(/*repeatCount=*/1);
7476 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007477 mWindow->assertNoEvents();
7478}
7479
7480TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007481 sendAndConsumeKeyDown(/*deviceId=*/1);
7482 expectKeyRepeatOnce(/*repeatCount=*/1);
7483 sendAndConsumeKeyDown(/*deviceId=*/2);
7484 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007485 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00007486 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007487 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00007488 expectKeyRepeatOnce(/*repeatCount=*/2);
7489 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07007490 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00007491 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007492 mWindow->assertNoEvents();
7493}
7494
7495TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007496 sendAndConsumeKeyDown(/*deviceId=*/1);
7497 expectKeyRepeatOnce(/*repeatCount=*/1);
7498 sendAndConsumeKeyDown(/*deviceId=*/2);
7499 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007500 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00007501 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007502 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08007503 mWindow->assertNoEvents();
7504}
7505
liushenxiang42232912021-05-21 20:24:09 +08007506TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
7507 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00007508 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007509 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08007510 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
7511 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
7512 mWindow->assertNoEvents();
7513}
7514
Garfield Tan1c7bc862020-01-28 13:24:04 -08007515TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007516 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007517 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007518 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007519 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
7520 ASSERT_NE(nullptr, repeatEvent);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007521 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007522 IdGenerator::getSource(repeatEvent->getId()));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007523 }
7524}
7525
7526TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007527 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007528 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007529
7530 std::unordered_set<int32_t> idSet;
7531 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007532 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
7533 ASSERT_NE(nullptr, repeatEvent);
7534 int32_t id = repeatEvent->getId();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007535 EXPECT_EQ(idSet.end(), idSet.find(id));
7536 idSet.insert(id);
7537 }
7538}
7539
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007540/* Test InputDispatcher for MultiDisplay */
7541class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
7542public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007543 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007544 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08007545
Chris Yea209fde2020-07-22 13:54:51 -07007546 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007547 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007548 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007549
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007550 // Set focus window for primary display, but focused display would be second one.
7551 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07007552 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007553 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
7554
Vishnu Nair958da932020-08-21 17:12:37 -07007555 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007556 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08007557
Chris Yea209fde2020-07-22 13:54:51 -07007558 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007559 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007560 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007561 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007562 // Set focus display to second one.
7563 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
7564 // Set focus window for second display.
7565 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07007566 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007567 mDispatcher->onWindowInfosChanged(
7568 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007569 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007570 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007571 }
7572
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007573 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007574 InputDispatcherTest::TearDown();
7575
Chris Yea209fde2020-07-22 13:54:51 -07007576 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007577 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07007578 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007579 windowInSecondary.clear();
7580 }
7581
7582protected:
Chris Yea209fde2020-07-22 13:54:51 -07007583 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007584 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07007585 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007586 sp<FakeWindowHandle> windowInSecondary;
7587};
7588
7589TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
7590 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007591 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007592 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007593 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007594 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08007595 windowInSecondary->assertNoEvents();
7596
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007597 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007598 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007599 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007600 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007601 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007602 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08007603}
7604
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007605TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08007606 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007607 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007608 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007609 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007610 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08007611 windowInSecondary->assertNoEvents();
7612
7613 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007614 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007615 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007616 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007617 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08007618
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007619 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007620 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08007621
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007622 // Old focus should receive a cancel event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007623 windowInSecondary->consumeKeyUp(ADISPLAY_ID_NONE, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08007624
7625 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007626 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08007627 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007628 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08007629 windowInSecondary->assertNoEvents();
7630}
7631
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007632// Test per-display input monitors for motion event.
7633TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08007634 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007635 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007636 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007637 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007638
7639 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007640 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007641 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007642 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007643 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007644 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007645 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007646 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007647
7648 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007649 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007650 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007651 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007652 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007653 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007654 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08007655 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007656
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007657 // Lift up the touch from the second display
7658 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007659 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007660 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7661 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
7662 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
7663
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007664 // Test inject a non-pointer motion event.
7665 // If specific a display, it will dispatch to the focused window of particular display,
7666 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007667 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007668 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007669 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007670 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007671 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007672 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007673 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007674}
7675
7676// Test per-display input monitors for key event.
7677TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007678 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08007679 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007680 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007681 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007682 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007683
7684 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007685 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007686 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007687 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007688 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007689 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007690 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007691}
7692
Vishnu Nair958da932020-08-21 17:12:37 -07007693TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
7694 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007695 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007696 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007697 mDispatcher->onWindowInfosChanged(
7698 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
7699 *windowInSecondary->getInfo()},
7700 {},
7701 0,
7702 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007703 setFocusedWindow(secondWindowInPrimary);
7704 windowInPrimary->consumeFocusEvent(false);
7705 secondWindowInPrimary->consumeFocusEvent(true);
7706
7707 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007708 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7709 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007710 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007711 windowInPrimary->assertNoEvents();
7712 windowInSecondary->assertNoEvents();
7713 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7714}
7715
Arthur Hungdfd528e2021-12-08 13:23:04 +00007716TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
7717 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007718 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007719 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007720 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007721
7722 // Test touch down on primary display.
7723 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007724 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007725 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7726 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7727 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
7728
7729 // Test touch down on second display.
7730 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007731 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007732 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7733 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
7734 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
7735
7736 // Trigger cancel touch.
7737 mDispatcher->cancelCurrentTouch();
7738 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7739 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7740 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
7741 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
7742
7743 // Test inject a move motion event, no window/monitor should receive the event.
7744 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007745 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007746 ADISPLAY_ID_DEFAULT, {110, 200}))
7747 << "Inject motion event should return InputEventInjectionResult::FAILED";
7748 windowInPrimary->assertNoEvents();
7749 monitorInPrimary.assertNoEvents();
7750
7751 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007752 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007753 SECOND_DISPLAY_ID, {110, 200}))
7754 << "Inject motion event should return InputEventInjectionResult::FAILED";
7755 windowInSecondary->assertNoEvents();
7756 monitorInSecondary.assertNoEvents();
7757}
7758
Hu Guocb134f12023-12-23 13:42:44 +00007759/**
7760 * Send a key to the primary display and to the secondary display.
7761 * Then cause the key on the primary display to be canceled by sending in a stale key.
7762 * Ensure that the key on the primary display is canceled, and that the key on the secondary display
7763 * does not get canceled.
7764 */
7765TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture) {
7766 // Send a key down on primary display
7767 mDispatcher->notifyKey(
7768 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7769 .displayId(ADISPLAY_ID_DEFAULT)
7770 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7771 .build());
7772 windowInPrimary->consumeKeyEvent(
7773 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7774 windowInSecondary->assertNoEvents();
7775
7776 // Send a key down on second display
7777 mDispatcher->notifyKey(
7778 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7779 .displayId(SECOND_DISPLAY_ID)
7780 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7781 .build());
7782 windowInSecondary->consumeKeyEvent(
7783 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7784 windowInPrimary->assertNoEvents();
7785
7786 // Send a valid key up event on primary display that will be dropped because it is stale
7787 NotifyKeyArgs staleKeyUp =
7788 KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
7789 .displayId(ADISPLAY_ID_DEFAULT)
7790 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7791 .build();
7792 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7793 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7794 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7795 mDispatcher->notifyKey(staleKeyUp);
7796
7797 // Only the key gesture corresponding to the dropped event should receive the cancel event.
7798 // Therefore, windowInPrimary should get the cancel event and windowInSecondary should not
7799 // receive any events.
7800 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
7801 WithDisplayId(ADISPLAY_ID_DEFAULT),
7802 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7803 windowInSecondary->assertNoEvents();
7804}
7805
7806/**
7807 * Similar to 'WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture' but for motion events.
7808 */
7809TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropMotionEvent_OnlyCancelCorrespondingGesture) {
7810 // Send touch down on primary display.
7811 mDispatcher->notifyMotion(
7812 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7813 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7814 .displayId(ADISPLAY_ID_DEFAULT)
7815 .build());
7816 windowInPrimary->consumeMotionEvent(
7817 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7818 windowInSecondary->assertNoEvents();
7819
7820 // Send touch down on second display.
7821 mDispatcher->notifyMotion(
7822 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7823 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7824 .displayId(SECOND_DISPLAY_ID)
7825 .build());
7826 windowInPrimary->assertNoEvents();
7827 windowInSecondary->consumeMotionEvent(
7828 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7829
7830 // inject a valid MotionEvent on primary display that will be stale when it arrives.
7831 NotifyMotionArgs staleMotionUp =
7832 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7833 .displayId(ADISPLAY_ID_DEFAULT)
7834 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7835 .build();
7836 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7837 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7838 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7839 mDispatcher->notifyMotion(staleMotionUp);
7840
7841 // For stale motion events, we let the gesture to complete. This behaviour is different from key
7842 // events, where we would cancel the current keys instead.
7843 windowInPrimary->consumeMotionEvent(WithMotionAction(ACTION_UP));
7844 windowInSecondary->assertNoEvents();
7845}
7846
Jackal Guof9696682018-10-05 12:23:23 +08007847class InputFilterTest : public InputDispatcherTest {
7848protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007849 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
7850 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08007851 NotifyMotionArgs motionArgs;
7852
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007853 motionArgs =
7854 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007855 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007856 motionArgs =
7857 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007858 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007859 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007860 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007861 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007862 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08007863 } else {
7864 mFakePolicy->assertFilterInputEventWasNotCalled();
7865 }
7866 }
7867
7868 void testNotifyKey(bool expectToBeFiltered) {
7869 NotifyKeyArgs keyArgs;
7870
7871 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007872 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007873 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007874 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007875 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007876
7877 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08007878 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007879 } else {
7880 mFakePolicy->assertFilterInputEventWasNotCalled();
7881 }
7882 }
7883};
7884
7885// Test InputFilter for MotionEvent
7886TEST_F(InputFilterTest, MotionEvent_InputFilter) {
7887 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007888 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7889 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007890
7891 // Enable InputFilter
7892 mDispatcher->setInputFilterEnabled(true);
7893 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007894 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
7895 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007896
7897 // Disable InputFilter
7898 mDispatcher->setInputFilterEnabled(false);
7899 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007900 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7901 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007902}
7903
7904// Test InputFilter for KeyEvent
7905TEST_F(InputFilterTest, KeyEvent_InputFilter) {
7906 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007907 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007908
7909 // Enable InputFilter
7910 mDispatcher->setInputFilterEnabled(true);
7911 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007912 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007913
7914 // Disable InputFilter
7915 mDispatcher->setInputFilterEnabled(false);
7916 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007917 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007918}
7919
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007920// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
7921// logical display coordinate space.
7922TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
7923 ui::Transform firstDisplayTransform;
7924 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7925 ui::Transform secondDisplayTransform;
7926 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
7927
7928 std::vector<gui::DisplayInfo> displayInfos(2);
7929 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
7930 displayInfos[0].transform = firstDisplayTransform;
7931 displayInfos[1].displayId = SECOND_DISPLAY_ID;
7932 displayInfos[1].transform = secondDisplayTransform;
7933
Patrick Williamsd828f302023-04-28 17:52:08 -05007934 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007935
7936 // Enable InputFilter
7937 mDispatcher->setInputFilterEnabled(true);
7938
7939 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007940 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
7941 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007942}
7943
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007944class InputFilterInjectionPolicyTest : public InputDispatcherTest {
7945protected:
7946 virtual void SetUp() override {
7947 InputDispatcherTest::SetUp();
7948
7949 /**
7950 * We don't need to enable input filter to test the injected event policy, but we enabled it
7951 * here to make the tests more realistic, since this policy only matters when inputfilter is
7952 * on.
7953 */
7954 mDispatcher->setInputFilterEnabled(true);
7955
7956 std::shared_ptr<InputApplicationHandle> application =
7957 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007958 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
7959 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007960
7961 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7962 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007963 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007964 setFocusedWindow(mWindow);
7965 mWindow->consumeFocusEvent(true);
7966 }
7967
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007968 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7969 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007970 KeyEvent event;
7971
7972 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7973 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
7974 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00007975 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007976 const int32_t additionalPolicyFlags =
7977 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
7978 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007979 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007980 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007981 policyFlags | additionalPolicyFlags));
7982
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007983 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007984 }
7985
7986 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7987 int32_t flags) {
7988 MotionEvent event;
7989 PointerProperties pointerProperties[1];
7990 PointerCoords pointerCoords[1];
7991 pointerProperties[0].clear();
7992 pointerProperties[0].id = 0;
7993 pointerCoords[0].clear();
7994 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
7995 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
7996
7997 ui::Transform identityTransform;
7998 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7999 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
8000 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
8001 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
8002 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07008003 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07008004 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00008005 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008006
8007 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
8008 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00008009 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00008010 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008011 policyFlags | additionalPolicyFlags));
8012
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008013 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008014 }
8015
8016private:
8017 sp<FakeWindowHandle> mWindow;
8018};
8019
8020TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008021 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
8022 // filter. Without it, the event will no different from a regularly injected event, and the
8023 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00008024 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
8025 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008026}
8027
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008028TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008029 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00008030 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008031 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
8032}
8033
8034TEST_F(InputFilterInjectionPolicyTest,
8035 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
8036 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00008037 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008038 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008039}
8040
8041TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00008042 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
8043 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008044}
8045
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08008046class InputDispatcherUserActivityPokeTests : public InputDispatcherTest {
8047protected:
8048 virtual void SetUp() override {
8049 InputDispatcherTest::SetUp();
8050
8051 std::shared_ptr<FakeApplicationHandle> application =
8052 std::make_shared<FakeApplicationHandle>();
8053 application->setDispatchingTimeout(100ms);
8054 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
8055 ADISPLAY_ID_DEFAULT);
Yeabkal Wubshit222d83d2024-01-24 18:00:09 +00008056 mWindow->setFrame(Rect(0, 0, 100, 100));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08008057 mWindow->setDispatchingTimeout(100ms);
8058 mWindow->setFocusable(true);
8059
8060 // Set focused application.
8061 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8062
8063 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
8064 setFocusedWindow(mWindow);
8065 mWindow->consumeFocusEvent(true);
8066 }
8067
8068 void notifyAndConsumeMotion(int32_t action, uint32_t source, int32_t displayId,
8069 nsecs_t eventTime) {
8070 mDispatcher->notifyMotion(MotionArgsBuilder(action, source)
8071 .displayId(displayId)
8072 .eventTime(eventTime)
8073 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8074 .build());
8075 mWindow->consumeMotionEvent(WithMotionAction(action));
8076 }
8077
8078private:
8079 sp<FakeWindowHandle> mWindow;
8080};
8081
8082TEST_F_WITH_FLAGS(
8083 InputDispatcherUserActivityPokeTests, MinPokeTimeObserved,
8084 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8085 rate_limit_user_activity_poke_in_dispatcher))) {
8086 mDispatcher->setMinTimeBetweenUserActivityPokes(50ms);
8087
8088 // First event of type TOUCH. Should poke.
8089 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8090 milliseconds_to_nanoseconds(50));
8091 mFakePolicy->assertUserActivityPoked(
8092 {{milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8093
8094 // 80ns > 50ns has passed since previous TOUCH event. Should poke.
8095 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8096 milliseconds_to_nanoseconds(130));
8097 mFakePolicy->assertUserActivityPoked(
8098 {{milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8099
8100 // First event of type OTHER. Should poke (despite being within 50ns of previous TOUCH event).
8101 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8102 milliseconds_to_nanoseconds(135));
8103 mFakePolicy->assertUserActivityPoked(
8104 {{milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER, ADISPLAY_ID_DEFAULT}});
8105
8106 // Within 50ns of previous TOUCH event. Should NOT poke.
8107 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8108 milliseconds_to_nanoseconds(140));
8109 mFakePolicy->assertUserActivityNotPoked();
8110
8111 // Within 50ns of previous OTHER event. Should NOT poke.
8112 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8113 milliseconds_to_nanoseconds(150));
8114 mFakePolicy->assertUserActivityNotPoked();
8115
8116 // Within 50ns of previous TOUCH event (which was at time 130). Should NOT poke.
8117 // Note that STYLUS is mapped to TOUCH user activity, since it's a pointer-type source.
8118 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
8119 milliseconds_to_nanoseconds(160));
8120 mFakePolicy->assertUserActivityNotPoked();
8121
8122 // 65ns > 50ns has passed since previous OTHER event. Should poke.
8123 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8124 milliseconds_to_nanoseconds(200));
8125 mFakePolicy->assertUserActivityPoked(
8126 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER, ADISPLAY_ID_DEFAULT}});
8127
8128 // 170ns > 50ns has passed since previous TOUCH event. Should poke.
8129 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
8130 milliseconds_to_nanoseconds(300));
8131 mFakePolicy->assertUserActivityPoked(
8132 {{milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8133
8134 // Assert that there's no more user activity poke event.
8135 mFakePolicy->assertUserActivityNotPoked();
8136}
8137
8138TEST_F_WITH_FLAGS(
8139 InputDispatcherUserActivityPokeTests, DefaultMinPokeTimeOf100MsUsed,
8140 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8141 rate_limit_user_activity_poke_in_dispatcher))) {
8142 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8143 milliseconds_to_nanoseconds(200));
8144 mFakePolicy->assertUserActivityPoked(
8145 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8146
8147 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8148 milliseconds_to_nanoseconds(280));
8149 mFakePolicy->assertUserActivityNotPoked();
8150
8151 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8152 milliseconds_to_nanoseconds(340));
8153 mFakePolicy->assertUserActivityPoked(
8154 {{milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8155}
8156
8157TEST_F_WITH_FLAGS(
8158 InputDispatcherUserActivityPokeTests, ZeroMinPokeTimeDisablesRateLimiting,
8159 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8160 rate_limit_user_activity_poke_in_dispatcher))) {
8161 mDispatcher->setMinTimeBetweenUserActivityPokes(0ms);
8162
8163 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20);
8164 mFakePolicy->assertUserActivityPoked();
8165
8166 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 30);
8167 mFakePolicy->assertUserActivityPoked();
8168}
8169
chaviwfd6d3512019-03-25 13:23:49 -07008170class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008171 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07008172 InputDispatcherTest::SetUp();
8173
Chris Yea209fde2020-07-22 13:54:51 -07008174 std::shared_ptr<FakeApplicationHandle> application =
8175 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008176 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008177 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07008178 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07008179
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008180 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008181 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008182 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07008183
8184 // Set focused application.
8185 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07008186 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07008187
8188 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008189 mDispatcher->onWindowInfosChanged(
8190 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008191 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008192 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07008193 }
8194
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008195 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07008196 InputDispatcherTest::TearDown();
8197
8198 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008199 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07008200 }
8201
8202protected:
8203 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008204 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008205 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07008206};
8207
8208// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
8209// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
8210// the onPointerDownOutsideFocus callback.
8211TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008212 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008213 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008214 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008215 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008216 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008217
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008218 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07008219 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
8220}
8221
8222// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
8223// DOWN on the window that doesn't have focus. Ensure no window received the
8224// onPointerDownOutsideFocus callback.
8225TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008226 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008227 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
8228 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008229 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008230 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008231
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008232 ASSERT_TRUE(mDispatcher->waitForIdle());
8233 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008234}
8235
8236// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
8237// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
8238TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08008239 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008240 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008241 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008242 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07008243
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008244 ASSERT_TRUE(mDispatcher->waitForIdle());
8245 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008246}
8247
8248// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
8249// DOWN on the window that already has focus. Ensure no window received the
8250// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008251TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008252 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008253 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008254 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008255 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008256 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008257
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008258 ASSERT_TRUE(mDispatcher->waitForIdle());
8259 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008260}
8261
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008262// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
8263// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
8264TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
8265 const MotionEvent event =
8266 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
8267 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008268 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008269 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
8270 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008271 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008272 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8273 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
8274
8275 ASSERT_TRUE(mDispatcher->waitForIdle());
8276 mFakePolicy->assertOnPointerDownWasNotCalled();
8277 // Ensure that the unfocused window did not receive any FOCUS events.
8278 mUnfocusedWindow->assertNoEvents();
8279}
8280
chaviwaf87b3e2019-10-01 16:59:28 -07008281// These tests ensures we can send touch events to a single client when there are multiple input
8282// windows that point to the same client token.
8283class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
8284 virtual void SetUp() override {
8285 InputDispatcherTest::SetUp();
8286
Chris Yea209fde2020-07-22 13:54:51 -07008287 std::shared_ptr<FakeApplicationHandle> application =
8288 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008289 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
8290 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07008291 mWindow1->setFrame(Rect(0, 0, 100, 100));
8292
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00008293 mWindow2 = mWindow1->clone(ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07008294 mWindow2->setFrame(Rect(100, 100, 200, 200));
8295
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008296 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07008297 }
8298
8299protected:
8300 sp<FakeWindowHandle> mWindow1;
8301 sp<FakeWindowHandle> mWindow2;
8302
8303 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05008304 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07008305 vec2 vals = windowInfo->transform.transform(point.x, point.y);
8306 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07008307 }
8308
8309 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
8310 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008311 const std::string name = window->getName();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008312 std::unique_ptr<MotionEvent> motionEvent =
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008313 window->consumeMotionEvent(WithMotionAction(expectedAction));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008314 ASSERT_NE(nullptr, motionEvent);
8315 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07008316
8317 for (size_t i = 0; i < points.size(); i++) {
8318 float expectedX = points[i].x;
8319 float expectedY = points[i].y;
8320
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008321 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07008322 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008323 << ", got " << motionEvent->getX(i);
8324 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07008325 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008326 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07008327 }
8328 }
chaviw9eaa22c2020-07-01 16:21:27 -07008329
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008330 void touchAndAssertPositions(sp<FakeWindowHandle> touchedWindow, int32_t action,
8331 const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07008332 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008333 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
8334 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07008335
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008336 consumeMotionEvent(touchedWindow, action, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008337 }
chaviwaf87b3e2019-10-01 16:59:28 -07008338};
8339
8340TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
8341 // Touch Window 1
8342 PointF touchedPoint = {10, 10};
8343 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008344 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008345
8346 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008347 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008348
8349 // Touch Window 2
8350 touchedPoint = {150, 150};
8351 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008352 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008353}
8354
chaviw9eaa22c2020-07-01 16:21:27 -07008355TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
8356 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07008357 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008358 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07008359
8360 // Touch Window 1
8361 PointF touchedPoint = {10, 10};
8362 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008363 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008364 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008365 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008366
8367 // Touch Window 2
8368 touchedPoint = {150, 150};
8369 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008370 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
8371 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008372
chaviw9eaa22c2020-07-01 16:21:27 -07008373 // Update the transform so rotation is set
8374 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008375 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008376 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008377 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008378}
8379
chaviw9eaa22c2020-07-01 16:21:27 -07008380TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008381 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008382 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008383
8384 // Touch Window 1
8385 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8386 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008387 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008388
8389 // Touch Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008390 // Since this is part of the same touch gesture that has already been dispatched to Window 1,
8391 // the touch stream from Window 2 will be merged with the stream in Window 1. The merged stream
8392 // will continue to be dispatched through Window 1.
chaviw9eaa22c2020-07-01 16:21:27 -07008393 touchedPoints.push_back(PointF{150, 150});
8394 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008395 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008396
chaviw9eaa22c2020-07-01 16:21:27 -07008397 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008398 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008399 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008400
chaviw9eaa22c2020-07-01 16:21:27 -07008401 // Update the transform so rotation is set for Window 2
8402 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008403 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008404 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008405 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008406}
8407
chaviw9eaa22c2020-07-01 16:21:27 -07008408TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008409 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008410 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008411
8412 // Touch Window 1
8413 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8414 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008415 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008416
8417 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07008418 touchedPoints.push_back(PointF{150, 150});
8419 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008420
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008421 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008422
8423 // Move both windows
8424 touchedPoints = {{20, 20}, {175, 175}};
8425 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8426 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8427
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008428 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008429
chaviw9eaa22c2020-07-01 16:21:27 -07008430 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008431 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008432 expectedPoints.pop_back();
8433
8434 // Touch Window 2
8435 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008436 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008437 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008438 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008439
8440 // Move both windows
8441 touchedPoints = {{20, 20}, {175, 175}};
8442 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8443 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8444
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008445 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008446}
8447
8448TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
8449 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008450 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008451
8452 // Touch Window 1
8453 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8454 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008455 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008456
8457 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07008458 touchedPoints.push_back(PointF{150, 150});
8459 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008460
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008461 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008462
8463 // Move both windows
8464 touchedPoints = {{20, 20}, {175, 175}};
8465 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8466 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8467
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008468 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008469}
8470
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07008471/**
8472 * When one of the windows is slippery, the touch should not slip into the other window with the
8473 * same input channel.
8474 */
8475TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
8476 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008477 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07008478
8479 // Touch down in window 1
8480 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8481 ADISPLAY_ID_DEFAULT, {{50, 50}}));
8482 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
8483
8484 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
8485 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
8486 // getting generated.
8487 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8488 ADISPLAY_ID_DEFAULT, {{150, 150}}));
8489
8490 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
8491}
8492
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008493/**
8494 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
8495 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
8496 * that the pointer is hovering over may have a different transform.
8497 */
8498TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008499 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008500
8501 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008502 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
8503 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8504 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008505 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
8506 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008507 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008508 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8509 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
8510 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008511 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008512 consumeMotionEvent(mWindow2, ACTION_HOVER_ENTER,
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008513 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
8514}
8515
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008516class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
8517 virtual void SetUp() override {
8518 InputDispatcherTest::SetUp();
8519
Chris Yea209fde2020-07-22 13:54:51 -07008520 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008521 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008522 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
8523 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008524 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008525 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07008526 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008527
8528 // Set focused application.
8529 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8530
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008531 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008532 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008533 mWindow->consumeFocusEvent(true);
8534 }
8535
8536 virtual void TearDown() override {
8537 InputDispatcherTest::TearDown();
8538 mWindow.clear();
8539 }
8540
8541protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008542 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07008543 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008544 sp<FakeWindowHandle> mWindow;
8545 static constexpr PointF WINDOW_LOCATION = {20, 20};
8546
8547 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008548 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
8549 .x(WINDOW_LOCATION.x)
8550 .y(WINDOW_LOCATION.y);
8551 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8552 .pointer(touchingPointer)
8553 .build());
8554 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8555 .pointer(touchingPointer)
8556 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008557 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008558
8559 sp<FakeWindowHandle> addSpyWindow() {
8560 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008561 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008562 spy->setTrustedOverlay(true);
8563 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008564 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008565 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008566 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008567 return spy;
8568 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008569};
8570
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008571// Send a tap and respond, which should not cause an ANR.
8572TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
8573 tapOnWindow();
8574 mWindow->consumeMotionDown();
8575 mWindow->consumeMotionUp();
8576 ASSERT_TRUE(mDispatcher->waitForIdle());
8577 mFakePolicy->assertNotifyAnrWasNotCalled();
8578}
8579
8580// Send a regular key and respond, which should not cause an ANR.
8581TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008582 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008583 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8584 ASSERT_TRUE(mDispatcher->waitForIdle());
8585 mFakePolicy->assertNotifyAnrWasNotCalled();
8586}
8587
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008588TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
8589 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008590 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008591 mWindow->consumeFocusEvent(false);
8592
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008593 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008594 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8595 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00008596 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008597 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008598 // Key will not go to window because we have no focused window.
8599 // The 'no focused window' ANR timer should start instead.
8600
8601 // Now, the focused application goes away.
8602 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
8603 // The key should get dropped and there should be no ANR.
8604
8605 ASSERT_TRUE(mDispatcher->waitForIdle());
8606 mFakePolicy->assertNotifyAnrWasNotCalled();
8607}
8608
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008609// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008610// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8611// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008612TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008613 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008614 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008615 WINDOW_LOCATION));
8616
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008617 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008618 ASSERT_TRUE(sequenceNum);
8619 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008620 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008621
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008622 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008623 mWindow->consumeMotionEvent(
8624 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008625 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008626 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008627}
8628
8629// Send a key to the app and have the app not respond right away.
8630TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
8631 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008632 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008633 const auto [sequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008634 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008635 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008636 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008637 ASSERT_TRUE(mDispatcher->waitForIdle());
8638}
8639
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008640// We have a focused application, but no focused window
8641TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008642 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008643 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008644 mWindow->consumeFocusEvent(false);
8645
8646 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008647 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008648 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008649 WINDOW_LOCATION));
8650 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
8651 mDispatcher->waitForIdle();
8652 mFakePolicy->assertNotifyAnrWasNotCalled();
8653
8654 // Once a focused event arrives, we get an ANR for this application
8655 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8656 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008657 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008658 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008659 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008660 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008661 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07008662 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008663 ASSERT_TRUE(mDispatcher->waitForIdle());
8664}
8665
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008666/**
8667 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
8668 * there will not be an ANR.
8669 */
8670TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
8671 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008672 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008673 mWindow->consumeFocusEvent(false);
8674
8675 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07008676 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
8677 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008678 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
8679 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
8680
8681 // Define a valid key down event that is stale (too old).
8682 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00008683 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00008684 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008685
8686 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
8687
8688 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00008689 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008690 InputEventInjectionSync::WAIT_FOR_RESULT,
8691 INJECT_EVENT_TIMEOUT, policyFlags);
8692 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
8693 << "Injection should fail because the event is stale";
8694
8695 ASSERT_TRUE(mDispatcher->waitForIdle());
8696 mFakePolicy->assertNotifyAnrWasNotCalled();
8697 mWindow->assertNoEvents();
8698}
8699
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008700// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008701// Make sure that we don't notify policy twice about the same ANR.
8702TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008703 const std::chrono::duration appTimeout = 400ms;
8704 mApplication->setDispatchingTimeout(appTimeout);
8705 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8706
Vishnu Nair47074b82020-08-14 11:54:47 -07008707 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008708 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008709 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008710
8711 // Once a focused event arrives, we get an ANR for this application
8712 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8713 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008714 const std::chrono::duration eventInjectionTimeout = 100ms;
8715 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008716 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008717 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008718 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
8719 /*allowKeyRepeat=*/false);
8720 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
8721 << "result=" << ftl::enum_string(result);
8722 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
8723 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
8724 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
8725 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008726
Vishnu Naire4df8752022-09-08 09:17:55 -07008727 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008728 // ANR should not be raised again. It is up to policy to do that if it desires.
8729 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008730
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008731 // If we now get a focused window, the ANR should stop, but the policy handles that via
8732 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008733 ASSERT_TRUE(mDispatcher->waitForIdle());
8734}
8735
8736// We have a focused application, but no focused window
8737TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008738 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008739 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008740 mWindow->consumeFocusEvent(false);
8741
8742 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008743 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008744
Vishnu Naire4df8752022-09-08 09:17:55 -07008745 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8746 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008747
8748 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008749 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008750 ASSERT_TRUE(mDispatcher->waitForIdle());
8751 mWindow->assertNoEvents();
8752}
8753
8754/**
8755 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
8756 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
8757 * If we process 1 of the events, but ANR on the second event with the same timestamp,
8758 * the ANR mechanism should still work.
8759 *
8760 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
8761 * DOWN event, while not responding on the second one.
8762 */
8763TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
8764 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008765 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008766 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8767 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8768 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008769 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008770
8771 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008772 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008773 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8774 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8775 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008776 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008777
8778 // We have now sent down and up. Let's consume first event and then ANR on the second.
8779 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8780 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008781 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008782}
8783
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008784// A spy window can receive an ANR
8785TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
8786 sp<FakeWindowHandle> spy = addSpyWindow();
8787
8788 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008789 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008790 WINDOW_LOCATION));
8791 mWindow->consumeMotionDown();
8792
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008793 const auto [sequenceNum, _] = spy->receiveEvent(); // ACTION_DOWN
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008794 ASSERT_TRUE(sequenceNum);
8795 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008796 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008797
8798 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008799 spy->consumeMotionEvent(
8800 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008801 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008802 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008803}
8804
8805// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008806// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008807TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
8808 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008809
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008810 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008811 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008812 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008813 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008814
8815 // Stuck on the ACTION_UP
8816 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008817 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008818
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008819 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008820 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008821 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8822 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008823
8824 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8825 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008826 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008827 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008828 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008829}
8830
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008831// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008832// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008833TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
8834 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008835
8836 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008837 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8838 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008839
8840 mWindow->consumeMotionDown();
8841 // Stuck on the ACTION_UP
8842 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008843 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008844
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008845 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008846 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008847 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8848 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008849
8850 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8851 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008852 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008853 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008854 spy->assertNoEvents();
8855}
8856
8857TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008858 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008859
Prabir Pradhanfb549072023-10-05 19:17:36 +00008860 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008861
8862 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008863 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008864 WINDOW_LOCATION));
8865
8866 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8867 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
8868 ASSERT_TRUE(consumeSeq);
8869
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008870 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
8871 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008872
8873 monitor.finishEvent(*consumeSeq);
8874 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
8875
8876 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008877 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008878}
8879
8880// If a window is unresponsive, then you get anr. if the window later catches up and starts to
8881// process events, you don't get an anr. When the window later becomes unresponsive again, you
8882// get an ANR again.
8883// 1. tap -> block on ACTION_UP -> receive ANR
8884// 2. consume all pending events (= queue becomes healthy again)
8885// 3. tap again -> block on ACTION_UP again -> receive ANR second time
8886TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
8887 tapOnWindow();
8888
8889 mWindow->consumeMotionDown();
8890 // Block on ACTION_UP
8891 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008892 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008893 mWindow->consumeMotionUp(); // Now the connection should be healthy again
8894 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008895 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008896 mWindow->assertNoEvents();
8897
8898 tapOnWindow();
8899 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008900 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008901 mWindow->consumeMotionUp();
8902
8903 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008904 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008905 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008906 mWindow->assertNoEvents();
8907}
8908
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008909// If a connection remains unresponsive for a while, make sure policy is only notified once about
8910// it.
8911TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008912 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008913 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008914 WINDOW_LOCATION));
8915
8916 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008917 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008918 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008919 // 'notifyConnectionUnresponsive' should only be called once per connection
8920 mFakePolicy->assertNotifyAnrWasNotCalled();
8921 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008922 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008923 mWindow->consumeMotionEvent(
8924 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008925 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008926 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008927 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008928 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008929}
8930
8931/**
8932 * 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 -07008933 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008934 */
8935TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008936 // The timeouts in this test are established by relying on the fact that the "key waiting for
8937 // events timeout" is equal to 500ms.
8938 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008939 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008940 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008941
8942 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008943 const auto& [downSequenceNum, downEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008944 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008945 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008946 ASSERT_TRUE(upSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008947
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008948 // Don't finish the events yet, and send a key
8949 mDispatcher->notifyKey(
8950 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
8951 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8952 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008953 // Key will not be sent to the window, yet, because the window is still processing events
8954 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008955 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008956 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008957
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008958 std::this_thread::sleep_for(400ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008959 // if we wait long enough though, dispatcher will give up, and still send the key
8960 // to the focused window, even though we have not yet finished the motion event
8961 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8962 mWindow->finishEvent(*downSequenceNum);
8963 mWindow->finishEvent(*upSequenceNum);
8964}
8965
8966/**
8967 * If a window is processing a motion event, and then a key event comes in, the key event should
8968 * not go to the focused window until the motion is processed.
8969 * If then a new motion comes in, then the pending key event should be going to the currently
8970 * focused window right away.
8971 */
8972TEST_F(InputDispatcherSingleWindowAnr,
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008973 PendingKey_IsDeliveredWhileMotionIsProcessingAndNewTouchComesIn) {
8974 // The timeouts in this test are established by relying on the fact that the "key waiting for
8975 // events timeout" is equal to 500ms.
8976 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008977 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008978 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008979
8980 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008981 const auto& [downSequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008982 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008983 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008984 ASSERT_TRUE(upSequenceNum);
8985 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008986 mDispatcher->notifyKey(
8987 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
8988 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8989 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008990 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008991 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008992
8993 // Now tap down again. It should cause the pending key to go to the focused window right away.
8994 tapOnWindow();
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008995 // Now that we tapped, we should receive the key immediately.
8996 // Since there's still room for slowness, we use 200ms, which is much less than
8997 // the "key waiting for events' timeout of 500ms minus the already waited 100ms duration.
8998 std::unique_ptr<InputEvent> keyEvent = mWindow->consume(200ms);
8999 ASSERT_NE(nullptr, keyEvent);
9000 ASSERT_EQ(InputEventType::KEY, keyEvent->getType());
9001 ASSERT_THAT(static_cast<KeyEvent&>(*keyEvent), WithKeyAction(AKEY_EVENT_ACTION_DOWN));
9002 // it doesn't matter that we haven't ack'd the other events yet. We can finish events in any
9003 // order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009004 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
9005 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08009006 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9007 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009008 mWindow->assertNoEvents();
9009}
9010
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07009011/**
9012 * Send an event to the app and have the app not respond right away.
9013 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
9014 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
9015 * At some point, the window becomes responsive again.
9016 * Ensure that subsequent events get dropped, and the next gesture is delivered.
9017 */
9018TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
9019 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9020 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
9021 .build());
9022
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009023 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07009024 ASSERT_TRUE(sequenceNum);
9025 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9026 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
9027
9028 mWindow->finishEvent(*sequenceNum);
9029 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
9030 ASSERT_TRUE(mDispatcher->waitForIdle());
9031 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
9032
9033 // Now that the window is responsive, let's continue the gesture.
9034 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9035 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9036 .build());
9037
9038 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9039 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9040 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
9041 .build());
9042
9043 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9044 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9045 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
9046 .build());
9047 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9048 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9049 .build());
9050 // We already canceled this pointer, so the window shouldn't get any new events.
9051 mWindow->assertNoEvents();
9052
9053 // Start another one.
9054 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9055 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
9056 .build());
9057 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9058}
9059
Prabir Pradhanfc364722024-02-08 17:51:20 +00009060// Send an event to the app and have the app not respond right away. Then remove the app window.
9061// When the window is removed, the dispatcher will cancel the events for that window.
9062// So InputDispatcher will enqueue ACTION_CANCEL event as well.
9063TEST_F(InputDispatcherSingleWindowAnr, AnrAfterWindowRemoval) {
9064 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9065 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9066 {WINDOW_LOCATION}));
9067
9068 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
9069 ASSERT_TRUE(sequenceNum);
9070
9071 // Remove the window, but the input channel should remain alive.
9072 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
9073
9074 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9075 // Since the window was removed, Dispatcher does not know the PID associated with the window
9076 // anymore, so the policy is notified without the PID.
9077 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken(),
9078 /*pid=*/std::nullopt);
9079
9080 mWindow->finishEvent(*sequenceNum);
9081 // The cancellation was generated when the window was removed, along with the focus event.
9082 mWindow->consumeMotionEvent(
9083 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
9084 mWindow->consumeFocusEvent(false);
9085 ASSERT_TRUE(mDispatcher->waitForIdle());
9086 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
9087}
9088
9089// Send an event to the app and have the app not respond right away. Wait for the policy to be
9090// notified of the unresponsive window, then remove the app window.
9091TEST_F(InputDispatcherSingleWindowAnr, AnrFollowedByWindowRemoval) {
9092 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9093 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9094 {WINDOW_LOCATION}));
9095
9096 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
9097 ASSERT_TRUE(sequenceNum);
9098 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9099 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
9100
9101 // Remove the window, but the input channel should remain alive.
9102 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
9103
9104 mWindow->finishEvent(*sequenceNum);
9105 // The cancellation was generated during the ANR, and the window lost focus when it was removed.
9106 mWindow->consumeMotionEvent(
9107 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
9108 mWindow->consumeFocusEvent(false);
9109 ASSERT_TRUE(mDispatcher->waitForIdle());
9110 // Since the window was removed, Dispatcher does not know the PID associated with the window
9111 // becoming responsive, so the policy is notified without the PID.
9112 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
9113}
9114
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009115class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
9116 virtual void SetUp() override {
9117 InputDispatcherTest::SetUp();
9118
Chris Yea209fde2020-07-22 13:54:51 -07009119 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009120 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009121 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
9122 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009123 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009124 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009125 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009126
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009127 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
9128 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009129 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009130 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009131
9132 // Set focused application.
9133 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07009134 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009135
9136 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009137 mDispatcher->onWindowInfosChanged(
9138 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009139 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009140 mFocusedWindow->consumeFocusEvent(true);
9141 }
9142
9143 virtual void TearDown() override {
9144 InputDispatcherTest::TearDown();
9145
9146 mUnfocusedWindow.clear();
9147 mFocusedWindow.clear();
9148 }
9149
9150protected:
Chris Yea209fde2020-07-22 13:54:51 -07009151 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009152 sp<FakeWindowHandle> mUnfocusedWindow;
9153 sp<FakeWindowHandle> mFocusedWindow;
9154 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
9155 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
9156 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
9157
9158 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
9159
9160 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
9161
9162private:
9163 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009164 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009165 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009166 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009167 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009168 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009169 location));
9170 }
9171};
9172
9173// If we have 2 windows that are both unresponsive, the one with the shortest timeout
9174// should be ANR'd first.
9175TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009176 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009177 injectMotionEvent(*mDispatcher,
9178 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9179 AINPUT_SOURCE_TOUCHSCREEN)
9180 .pointer(PointerBuilder(0, ToolType::FINGER)
9181 .x(FOCUSED_WINDOW_LOCATION.x)
9182 .y(FOCUSED_WINDOW_LOCATION.y))
9183 .build()));
9184 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9185 injectMotionEvent(*mDispatcher,
9186 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
9187 AINPUT_SOURCE_TOUCHSCREEN)
9188 .pointer(PointerBuilder(0, ToolType::FINGER)
9189 .x(FOCUSED_WINDOW_LOCATION.x)
9190 .y(FOCUSED_WINDOW_LOCATION.y))
9191 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009192 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009193 mFocusedWindow->consumeMotionUp();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009194 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009195 // We consumed all events, so no ANR
9196 ASSERT_TRUE(mDispatcher->waitForIdle());
9197 mFakePolicy->assertNotifyAnrWasNotCalled();
9198
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009199 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009200 injectMotionEvent(*mDispatcher,
9201 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9202 AINPUT_SOURCE_TOUCHSCREEN)
9203 .pointer(PointerBuilder(0, ToolType::FINGER)
9204 .x(FOCUSED_WINDOW_LOCATION.x)
9205 .y(FOCUSED_WINDOW_LOCATION.y))
9206 .build()));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009207 const auto [unfocusedSequenceNum, _] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009208 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009209
9210 const std::chrono::duration timeout =
9211 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009212 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009213
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009214 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009215 mFocusedWindow->consumeMotionDown();
9216 // This cancel is generated because the connection was unresponsive
9217 mFocusedWindow->consumeMotionCancel();
9218 mFocusedWindow->assertNoEvents();
9219 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009220 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009221 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9222 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009223 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009224}
9225
9226// If we have 2 windows with identical timeouts that are both unresponsive,
9227// it doesn't matter which order they should have ANR.
9228// But we should receive ANR for both.
9229TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
9230 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009231 mUnfocusedWindow->setDispatchingTimeout(
9232 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009233 mDispatcher->onWindowInfosChanged(
9234 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009235
9236 tapOnFocusedWindow();
9237 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009238 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009239 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
9240 mFocusedWindow->getDispatchingTimeout(
9241 DISPATCHING_TIMEOUT)),
9242 mFakePolicy->getUnresponsiveWindowToken(0ms)};
9243
9244 ASSERT_THAT(anrConnectionTokens,
9245 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
9246 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009247
9248 ASSERT_TRUE(mDispatcher->waitForIdle());
9249 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009250
9251 mFocusedWindow->consumeMotionDown();
9252 mFocusedWindow->consumeMotionUp();
9253 mUnfocusedWindow->consumeMotionOutside();
9254
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009255 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
9256 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009257
9258 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009259 ASSERT_THAT(responsiveTokens,
9260 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
9261 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009262 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009263}
9264
9265// If a window is already not responding, the second tap on the same window should be ignored.
9266// We should also log an error to account for the dropped event (not tested here).
9267// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
9268TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
9269 tapOnFocusedWindow();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009270 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009271 // Receive the events, but don't respond
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009272 const auto [downEventSequenceNum, downEvent] = mFocusedWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009273 ASSERT_TRUE(downEventSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009274 const auto [upEventSequenceNum, upEvent] = mFocusedWindow->receiveEvent(); // ACTION_UP
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009275 ASSERT_TRUE(upEventSequenceNum);
9276 const std::chrono::duration timeout =
9277 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009278 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009279
9280 // Tap once again
9281 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009282 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009283 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009284 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009285 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009286 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009287 FOCUSED_WINDOW_LOCATION));
9288 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
9289 // valid touch target
9290 mUnfocusedWindow->assertNoEvents();
9291
9292 // Consume the first tap
9293 mFocusedWindow->finishEvent(*downEventSequenceNum);
9294 mFocusedWindow->finishEvent(*upEventSequenceNum);
9295 ASSERT_TRUE(mDispatcher->waitForIdle());
9296 // The second tap did not go to the focused window
9297 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009298 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08009299 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9300 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009301 mFakePolicy->assertNotifyAnrWasNotCalled();
9302}
9303
9304// If you tap outside of all windows, there will not be ANR
9305TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009306 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009307 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009308 LOCATION_OUTSIDE_ALL_WINDOWS));
9309 ASSERT_TRUE(mDispatcher->waitForIdle());
9310 mFakePolicy->assertNotifyAnrWasNotCalled();
9311}
9312
9313// Since the focused window is paused, tapping on it should not produce any events
9314TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
9315 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009316 mDispatcher->onWindowInfosChanged(
9317 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009318
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009319 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009320 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009321 FOCUSED_WINDOW_LOCATION));
9322
9323 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
9324 ASSERT_TRUE(mDispatcher->waitForIdle());
9325 // Should not ANR because the window is paused, and touches shouldn't go to it
9326 mFakePolicy->assertNotifyAnrWasNotCalled();
9327
9328 mFocusedWindow->assertNoEvents();
9329 mUnfocusedWindow->assertNoEvents();
9330}
9331
9332/**
9333 * 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 -07009334 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009335 * If a different window becomes focused at this time, the key should go to that window instead.
9336 *
9337 * Warning!!!
9338 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
9339 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009340 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009341 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
9342 *
9343 * If that value changes, this test should also change.
9344 */
9345TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
9346 // Set a long ANR timeout to prevent it from triggering
9347 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009348 mDispatcher->onWindowInfosChanged(
9349 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009350
9351 tapOnUnfocusedWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009352 const auto [downSequenceNum, downEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009353 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009354 const auto [upSequenceNum, upEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009355 ASSERT_TRUE(upSequenceNum);
9356 // Don't finish the events yet, and send a key
9357 // Injection will succeed because we will eventually give up and send the key to the focused
9358 // window even if motions are still being processed.
9359
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009360 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009361 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9362 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009363 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009364 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009365 // and the key remains pending, waiting for the touch events to be processed.
9366 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
9367 // under the hood.
9368 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
9369 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009370
9371 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07009372 mFocusedWindow->setFocusable(false);
9373 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009374 mDispatcher->onWindowInfosChanged(
9375 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009376 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009377
9378 // Focus events should precede the key events
9379 mUnfocusedWindow->consumeFocusEvent(true);
9380 mFocusedWindow->consumeFocusEvent(false);
9381
9382 // Finish the tap events, which should unblock dispatcher
9383 mUnfocusedWindow->finishEvent(*downSequenceNum);
9384 mUnfocusedWindow->finishEvent(*upSequenceNum);
9385
9386 // Now that all queues are cleared and no backlog in the connections, the key event
9387 // can finally go to the newly focused "mUnfocusedWindow".
9388 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9389 mFocusedWindow->assertNoEvents();
9390 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009391 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009392}
9393
9394// When the touch stream is split across 2 windows, and one of them does not respond,
9395// then ANR should be raised and the touch should be canceled for the unresponsive window.
9396// The other window should not be affected by that.
9397TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
9398 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00009399 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9400 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9401 {FOCUSED_WINDOW_LOCATION}));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009402 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009403
9404 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00009405 mDispatcher->notifyMotion(
9406 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9407 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009408
9409 const std::chrono::duration timeout =
9410 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009411 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009412
9413 mUnfocusedWindow->consumeMotionDown();
9414 mFocusedWindow->consumeMotionDown();
9415 // Focused window may or may not receive ACTION_MOVE
9416 // But it should definitely receive ACTION_CANCEL due to the ANR
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009417 const auto [moveOrCancelSequenceNum, event] = mFocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009418 ASSERT_TRUE(moveOrCancelSequenceNum);
9419 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
9420 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009421 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009422 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
9423 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
9424 mFocusedWindow->consumeMotionCancel();
9425 } else {
9426 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
9427 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009428 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009429 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9430 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009431
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009432 mUnfocusedWindow->assertNoEvents();
9433 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009434 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009435}
9436
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009437/**
9438 * If we have no focused window, and a key comes in, we start the ANR timer.
9439 * The focused application should add a focused window before the timer runs out to prevent ANR.
9440 *
9441 * If the user touches another application during this time, the key should be dropped.
9442 * Next, if a new focused window comes in, without toggling the focused application,
9443 * then no ANR should occur.
9444 *
9445 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
9446 * but in some cases the policy may not update the focused application.
9447 */
9448TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
9449 std::shared_ptr<FakeApplicationHandle> focusedApplication =
9450 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07009451 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009452 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
9453 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
9454 mFocusedWindow->setFocusable(false);
9455
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009456 mDispatcher->onWindowInfosChanged(
9457 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009458 mFocusedWindow->consumeFocusEvent(false);
9459
9460 // Send a key. The ANR timer should start because there is no focused window.
9461 // 'focusedApplication' will get blamed if this timer completes.
9462 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009463 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009464 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9465 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00009466 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009467 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009468
9469 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
9470 // then the injected touches won't cause the focused event to get dropped.
9471 // The dispatcher only checks for whether the queue should be pruned upon queueing.
9472 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
9473 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
9474 // For this test, it means that the key would get delivered to the window once it becomes
9475 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009476 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009477
9478 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00009479 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9480 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9481 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009482
9483 // We do not consume the motion right away, because that would require dispatcher to first
9484 // process (== drop) the key event, and by that time, ANR will be raised.
9485 // Set the focused window first.
9486 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009487 mDispatcher->onWindowInfosChanged(
9488 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009489 setFocusedWindow(mFocusedWindow);
9490 mFocusedWindow->consumeFocusEvent(true);
9491 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
9492 // to another application. This could be a bug / behaviour in the policy.
9493
9494 mUnfocusedWindow->consumeMotionDown();
9495
9496 ASSERT_TRUE(mDispatcher->waitForIdle());
9497 // Should not ANR because we actually have a focused window. It was just added too slowly.
9498 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
9499}
9500
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -08009501/**
9502 * If we are pruning input queue, we should never drop pointer events. Otherwise, we risk having
9503 * an inconsistent event stream inside the dispatcher. In this test, we make sure that the
9504 * dispatcher doesn't prune pointer events incorrectly.
9505 *
9506 * This test reproduces a crash in InputDispatcher.
9507 * To reproduce the crash, we need to simulate the conditions for "pruning input queue" to occur.
9508 *
9509 * Keep the currently focused application (mApplication), and have no focused window.
9510 * We set up two additional windows:
9511 * 1) The navigation bar window. This simulates the system "NavigationBar", which is used in the
9512 * 3-button navigation mode. This window injects a BACK button when it's touched. 2) The application
9513 * window. This window is not focusable, but is touchable.
9514 *
9515 * We first touch the navigation bar, which causes it to inject a key. Since there's no focused
9516 * window, the dispatcher doesn't process this key, and all other events inside dispatcher are now
9517 * blocked. The dispatcher is waiting for 'mApplication' to add a focused window.
9518 *
9519 * Now, we touch "Another window". This window is owned by a different application than
9520 * 'mApplication'. This causes the dispatcher to stop waiting for 'mApplication' to add a focused
9521 * window. Now, the "pruning input queue" behaviour should kick in, and the dispatcher should start
9522 * dropping the events from its queue. Ensure that no crash occurs.
9523 *
9524 * In this test, we are setting long timeouts to prevent ANRs and events dropped due to being stale.
9525 * This does not affect the test running time.
9526 */
9527TEST_F(InputDispatcherMultiWindowAnr, PruningInputQueueShouldNotDropPointerEvents) {
9528 std::shared_ptr<FakeApplicationHandle> systemUiApplication =
9529 std::make_shared<FakeApplicationHandle>();
9530 systemUiApplication->setDispatchingTimeout(3000ms);
9531 mFakePolicy->setStaleEventTimeout(3000ms);
9532 sp<FakeWindowHandle> navigationBar =
9533 sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
9534 ADISPLAY_ID_DEFAULT);
9535 navigationBar->setFocusable(false);
9536 navigationBar->setWatchOutsideTouch(true);
9537 navigationBar->setFrame(Rect(0, 0, 100, 100));
9538
9539 mApplication->setDispatchingTimeout(3000ms);
9540 // 'mApplication' is already focused, but we call it again here to make it explicit.
9541 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
9542
9543 std::shared_ptr<FakeApplicationHandle> anotherApplication =
9544 std::make_shared<FakeApplicationHandle>();
9545 sp<FakeWindowHandle> appWindow =
9546 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
9547 ADISPLAY_ID_DEFAULT);
9548 appWindow->setFocusable(false);
9549 appWindow->setFrame(Rect(100, 100, 200, 200));
9550
9551 mDispatcher->onWindowInfosChanged(
9552 {{*navigationBar->getInfo(), *appWindow->getInfo()}, {}, 0, 0});
9553 // 'mFocusedWindow' is no longer in the dispatcher window list, and therefore loses focus
9554 mFocusedWindow->consumeFocusEvent(false);
9555
9556 // Touch down the navigation bar. It consumes the touch and injects a key into the dispatcher
9557 // in response.
9558 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9559 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9560 .build());
9561 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9562
9563 // Key will not be sent anywhere because we have no focused window. It will remain pending.
9564 // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
9565 InputEventInjectionResult result =
9566 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9567 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
9568 /*allowKeyRepeat=*/false);
9569 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
9570
9571 // Finish the gesture - lift up finger and inject ACTION_UP key event
9572 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9573 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9574 .build());
9575 result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9576 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
9577 /*allowKeyRepeat=*/false);
9578 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
9579 // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
9580 // getting any events yet.
9581 navigationBar->assertNoEvents();
9582
9583 // Now touch "Another window". This touch is going to a different application than the one we
9584 // are waiting for (which is 'mApplication').
9585 // This should cause the dispatcher to drop the pending focus-dispatched events (like the key
9586 // trying to be injected) and to continue processing the rest of the events in the original
9587 // order.
9588 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9589 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
9590 .build());
9591 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_UP));
9592 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
9593 appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9594
9595 appWindow->assertNoEvents();
9596 navigationBar->assertNoEvents();
9597}
9598
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009599// These tests ensure we cannot send touch events to a window that's positioned behind a window
9600// that has feature NO_INPUT_CHANNEL.
9601// Layout:
9602// Top (closest to user)
9603// mNoInputWindow (above all windows)
9604// mBottomWindow
9605// Bottom (furthest from user)
9606class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
9607 virtual void SetUp() override {
9608 InputDispatcherTest::SetUp();
9609
9610 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009611 mNoInputWindow =
9612 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
9613 "Window without input channel", ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009614 /*createInputChannel=*/false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009615 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009616 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
9617 // It's perfectly valid for this window to not have an associated input channel
9618
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009619 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
9620 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009621 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
9622
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009623 mDispatcher->onWindowInfosChanged(
9624 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009625 }
9626
9627protected:
9628 std::shared_ptr<FakeApplicationHandle> mApplication;
9629 sp<FakeWindowHandle> mNoInputWindow;
9630 sp<FakeWindowHandle> mBottomWindow;
9631};
9632
9633TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
9634 PointF touchedPoint = {10, 10};
9635
Prabir Pradhan678438e2023-04-13 19:32:51 +00009636 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9637 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9638 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009639
9640 mNoInputWindow->assertNoEvents();
9641 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
9642 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
9643 // and therefore should prevent mBottomWindow from receiving touches
9644 mBottomWindow->assertNoEvents();
9645}
9646
9647/**
9648 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
9649 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
9650 */
9651TEST_F(InputDispatcherMultiWindowOcclusionTests,
9652 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009653 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
9654 "Window with input channel and NO_INPUT_CHANNEL",
9655 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009656
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009657 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009658 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009659 mDispatcher->onWindowInfosChanged(
9660 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009661
9662 PointF touchedPoint = {10, 10};
9663
Prabir Pradhan678438e2023-04-13 19:32:51 +00009664 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9665 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9666 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009667
9668 mNoInputWindow->assertNoEvents();
9669 mBottomWindow->assertNoEvents();
9670}
9671
Vishnu Nair958da932020-08-21 17:12:37 -07009672class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
9673protected:
9674 std::shared_ptr<FakeApplicationHandle> mApp;
9675 sp<FakeWindowHandle> mWindow;
9676 sp<FakeWindowHandle> mMirror;
9677
9678 virtual void SetUp() override {
9679 InputDispatcherTest::SetUp();
9680 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009681 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009682 mMirror = mWindow->clone(ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07009683 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
9684 mWindow->setFocusable(true);
9685 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009686 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009687 }
9688};
9689
9690TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
9691 // Request focus on a mirrored window
9692 setFocusedWindow(mMirror);
9693
9694 // window gets focused
9695 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009696 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009697 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009698 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
9699}
9700
9701// A focused & mirrored window remains focused only if the window and its mirror are both
9702// focusable.
9703TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
9704 setFocusedWindow(mMirror);
9705
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009706 // window gets focused because it is above the mirror
Vishnu Nair958da932020-08-21 17:12:37 -07009707 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009708 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009709 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009710 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009711 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009712 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009713 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9714
9715 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009716 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009717
9718 // window loses focus since one of the windows associated with the token in not focusable
9719 mWindow->consumeFocusEvent(false);
9720
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009721 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009722 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009723 mWindow->assertNoEvents();
9724}
9725
9726// A focused & mirrored window remains focused until the window and its mirror both become
9727// invisible.
9728TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
9729 setFocusedWindow(mMirror);
9730
9731 // window gets focused
9732 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009733 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009734 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009735 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009736 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009737 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009738 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9739
9740 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009741 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009742
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009743 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009744 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009745 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009746 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009747 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009748 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9749
9750 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009751 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009752
9753 // window loses focus only after all windows associated with the token become invisible.
9754 mWindow->consumeFocusEvent(false);
9755
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009756 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009757 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009758 mWindow->assertNoEvents();
9759}
9760
9761// A focused & mirrored window remains focused until both windows are removed.
9762TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
9763 setFocusedWindow(mMirror);
9764
9765 // window gets focused
9766 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009767 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009768 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009769 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009770 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009771 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009772 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9773
9774 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009775 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009776
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009777 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009778 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009779 mMirror->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009780 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009781 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009782 mMirror->consumeKeyUp(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07009783
9784 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009785 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009786 mWindow->consumeFocusEvent(false);
9787
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009788 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009789 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009790 mWindow->assertNoEvents();
9791}
9792
9793// Focus request can be pending until one window becomes visible.
9794TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
9795 // Request focus on an invisible mirror.
9796 mWindow->setVisible(false);
9797 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009798 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009799 setFocusedWindow(mMirror);
9800
9801 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009802 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009803 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9804 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07009805
9806 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009807 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009808
9809 // window gets focused
9810 mWindow->consumeFocusEvent(true);
9811 // window gets the pending key event
9812 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9813}
Prabir Pradhan99987712020-11-10 18:43:05 -08009814
9815class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
9816protected:
9817 std::shared_ptr<FakeApplicationHandle> mApp;
9818 sp<FakeWindowHandle> mWindow;
9819 sp<FakeWindowHandle> mSecondWindow;
9820
9821 void SetUp() override {
9822 InputDispatcherTest::SetUp();
9823 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009824 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009825 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009826 mSecondWindow =
9827 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009828 mSecondWindow->setFocusable(true);
9829
9830 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009831 mDispatcher->onWindowInfosChanged(
9832 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08009833
9834 setFocusedWindow(mWindow);
9835 mWindow->consumeFocusEvent(true);
9836 }
9837
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009838 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009839 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08009840 }
9841
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009842 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
9843 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08009844 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009845 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
9846 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009847 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009848 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08009849 }
9850};
9851
9852TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
9853 // Ensure that capture cannot be obtained for unfocused windows.
9854 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
9855 mFakePolicy->assertSetPointerCaptureNotCalled();
9856 mSecondWindow->assertNoEvents();
9857
9858 // Ensure that capture can be enabled from the focus window.
9859 requestAndVerifyPointerCapture(mWindow, true);
9860
9861 // Ensure that capture cannot be disabled from a window that does not have capture.
9862 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
9863 mFakePolicy->assertSetPointerCaptureNotCalled();
9864
9865 // Ensure that capture can be disabled from the window with capture.
9866 requestAndVerifyPointerCapture(mWindow, false);
9867}
9868
9869TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009870 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009871
9872 setFocusedWindow(mSecondWindow);
9873
9874 // Ensure that the capture disabled event was sent first.
9875 mWindow->consumeCaptureEvent(false);
9876 mWindow->consumeFocusEvent(false);
9877 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009878 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009879
9880 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009881 notifyPointerCaptureChanged({});
9882 notifyPointerCaptureChanged(request);
9883 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08009884 mWindow->assertNoEvents();
9885 mSecondWindow->assertNoEvents();
9886 mFakePolicy->assertSetPointerCaptureNotCalled();
9887}
9888
9889TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009890 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009891
9892 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009893 notifyPointerCaptureChanged({});
9894 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009895
9896 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009897 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009898 mWindow->consumeCaptureEvent(false);
9899 mWindow->assertNoEvents();
9900}
9901
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009902TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
9903 requestAndVerifyPointerCapture(mWindow, true);
9904
9905 // The first window loses focus.
9906 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009907 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009908 mWindow->consumeCaptureEvent(false);
9909
9910 // Request Pointer Capture from the second window before the notification from InputReader
9911 // arrives.
9912 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009913 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009914
9915 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009916 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009917
9918 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009919 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009920
9921 mSecondWindow->consumeFocusEvent(true);
9922 mSecondWindow->consumeCaptureEvent(true);
9923}
9924
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009925TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
9926 // App repeatedly enables and disables capture.
9927 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9928 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9929 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9930 mFakePolicy->assertSetPointerCaptureCalled(false);
9931 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9932 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9933
9934 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
9935 // first request is now stale, this should do nothing.
9936 notifyPointerCaptureChanged(firstRequest);
9937 mWindow->assertNoEvents();
9938
9939 // InputReader notifies that the second request was enabled.
9940 notifyPointerCaptureChanged(secondRequest);
9941 mWindow->consumeCaptureEvent(true);
9942}
9943
Prabir Pradhan7092e262022-05-03 16:51:09 +00009944TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
9945 requestAndVerifyPointerCapture(mWindow, true);
9946
9947 // App toggles pointer capture off and on.
9948 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9949 mFakePolicy->assertSetPointerCaptureCalled(false);
9950
9951 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9952 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9953
9954 // InputReader notifies that the latest "enable" request was processed, while skipping over the
9955 // preceding "disable" request.
9956 notifyPointerCaptureChanged(enableRequest);
9957
9958 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
9959 // any notifications.
9960 mWindow->assertNoEvents();
9961}
9962
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009963/**
9964 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
9965 * mouse movements don't affect the previous mouse hovering state.
9966 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
9967 * HOVER_MOVE events).
9968 */
9969TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
9970 // Mouse hover on the window
9971 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
9972 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9973 .build());
9974 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9975 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9976 .build());
9977
9978 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
9979 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
9980
9981 // Start pointer capture
9982 requestAndVerifyPointerCapture(mWindow, true);
9983
9984 // Send some relative mouse movements and receive them in the window.
9985 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
9986 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
9987 .build());
9988 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
9989 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
9990
9991 // Stop pointer capture
9992 requestAndVerifyPointerCapture(mWindow, false);
9993
9994 // Continue hovering on the window
9995 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9996 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
9997 .build());
9998 mWindow->consumeMotionEvent(
9999 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
10000
10001 mWindow->assertNoEvents();
10002}
10003
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010004class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
10005protected:
10006 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +000010007
10008 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
10009 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
10010
10011 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
10012 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
10013
10014 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
10015 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
10016 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
10017 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
10018 MAXIMUM_OBSCURING_OPACITY);
10019
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010020 static constexpr gui::Uid TOUCHED_APP_UID{10001};
10021 static constexpr gui::Uid APP_B_UID{10002};
10022 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010023
10024 sp<FakeWindowHandle> mTouchWindow;
10025
10026 virtual void SetUp() override {
10027 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010028 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010029 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
10030 }
10031
10032 virtual void TearDown() override {
10033 InputDispatcherTest::TearDown();
10034 mTouchWindow.clear();
10035 }
10036
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010037 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -050010038 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010039 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010040 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010041 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010042 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010043 return window;
10044 }
10045
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010046 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010047 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
10048 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010049 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010050 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010051 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010052 return window;
10053 }
10054
10055 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010056 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10057 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10058 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010059 }
10060};
10061
10062TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010063 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010064 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010065 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010066
10067 touch();
10068
10069 mTouchWindow->assertNoEvents();
10070}
10071
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010072TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +000010073 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
10074 const sp<FakeWindowHandle>& w =
10075 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010076 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010077
10078 touch();
10079
10080 mTouchWindow->assertNoEvents();
10081}
10082
10083TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010084 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
10085 const sp<FakeWindowHandle>& w =
10086 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010087 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010088
10089 touch();
10090
10091 w->assertNoEvents();
10092}
10093
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010094TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010095 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010096 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010097
10098 touch();
10099
10100 mTouchWindow->consumeAnyMotionDown();
10101}
10102
10103TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010104 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010105 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010106 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010107 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010108
10109 touch({PointF{100, 100}});
10110
10111 mTouchWindow->consumeAnyMotionDown();
10112}
10113
10114TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010115 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010116 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010117 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010118
10119 touch();
10120
10121 mTouchWindow->consumeAnyMotionDown();
10122}
10123
10124TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
10125 const sp<FakeWindowHandle>& w =
10126 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010127 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010128
10129 touch();
10130
10131 mTouchWindow->consumeAnyMotionDown();
10132}
10133
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010134TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
10135 const sp<FakeWindowHandle>& w =
10136 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010137 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010138
10139 touch();
10140
10141 w->assertNoEvents();
10142}
10143
10144/**
10145 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
10146 * inside) while letting them pass-through. Note that even though touch passes through the occluding
10147 * window, the occluding window will still receive ACTION_OUTSIDE event.
10148 */
10149TEST_F(InputDispatcherUntrustedTouchesTest,
10150 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
10151 const sp<FakeWindowHandle>& w =
10152 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010153 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010154 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010155
10156 touch();
10157
10158 w->consumeMotionOutside();
10159}
10160
10161TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
10162 const sp<FakeWindowHandle>& w =
10163 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010164 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010165 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010166
10167 touch();
10168
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010169 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010170}
10171
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010172TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010173 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010174 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10175 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010176 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010177
10178 touch();
10179
10180 mTouchWindow->consumeAnyMotionDown();
10181}
10182
10183TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
10184 const sp<FakeWindowHandle>& w =
10185 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10186 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010187 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010188
10189 touch();
10190
10191 mTouchWindow->consumeAnyMotionDown();
10192}
10193
10194TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010195 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010196 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10197 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010198 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010199
10200 touch();
10201
10202 mTouchWindow->assertNoEvents();
10203}
10204
10205TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
10206 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
10207 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010208 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
10209 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010210 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010211 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
10212 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010213 mDispatcher->onWindowInfosChanged(
10214 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010215
10216 touch();
10217
10218 mTouchWindow->assertNoEvents();
10219}
10220
10221TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
10222 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
10223 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010224 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
10225 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010226 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010227 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
10228 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010229 mDispatcher->onWindowInfosChanged(
10230 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010231
10232 touch();
10233
10234 mTouchWindow->consumeAnyMotionDown();
10235}
10236
10237TEST_F(InputDispatcherUntrustedTouchesTest,
10238 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
10239 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010240 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10241 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010242 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010243 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10244 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010245 mDispatcher->onWindowInfosChanged(
10246 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010247
10248 touch();
10249
10250 mTouchWindow->consumeAnyMotionDown();
10251}
10252
10253TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
10254 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010255 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10256 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010257 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010258 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10259 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010260 mDispatcher->onWindowInfosChanged(
10261 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010262
10263 touch();
10264
10265 mTouchWindow->assertNoEvents();
10266}
10267
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010268TEST_F(InputDispatcherUntrustedTouchesTest,
10269 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
10270 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010271 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10272 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010273 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010274 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10275 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010276 mDispatcher->onWindowInfosChanged(
10277 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010278
10279 touch();
10280
10281 mTouchWindow->assertNoEvents();
10282}
10283
10284TEST_F(InputDispatcherUntrustedTouchesTest,
10285 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
10286 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010287 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10288 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010289 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010290 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10291 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010292 mDispatcher->onWindowInfosChanged(
10293 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010294
10295 touch();
10296
10297 mTouchWindow->consumeAnyMotionDown();
10298}
10299
10300TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
10301 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010302 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10303 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010304 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010305
10306 touch();
10307
10308 mTouchWindow->consumeAnyMotionDown();
10309}
10310
10311TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
10312 const sp<FakeWindowHandle>& w =
10313 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010314 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010315
10316 touch();
10317
10318 mTouchWindow->consumeAnyMotionDown();
10319}
10320
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010321TEST_F(InputDispatcherUntrustedTouchesTest,
10322 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
10323 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
10324 const sp<FakeWindowHandle>& w =
10325 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010326 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010327
10328 touch();
10329
10330 mTouchWindow->assertNoEvents();
10331}
10332
10333TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
10334 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
10335 const sp<FakeWindowHandle>& w =
10336 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010337 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010338
10339 touch();
10340
10341 mTouchWindow->consumeAnyMotionDown();
10342}
10343
10344TEST_F(InputDispatcherUntrustedTouchesTest,
10345 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
10346 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
10347 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010348 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10349 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010350 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010351
10352 touch();
10353
10354 mTouchWindow->consumeAnyMotionDown();
10355}
10356
10357TEST_F(InputDispatcherUntrustedTouchesTest,
10358 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
10359 const sp<FakeWindowHandle>& w1 =
10360 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
10361 OPACITY_BELOW_THRESHOLD);
10362 const sp<FakeWindowHandle>& w2 =
10363 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10364 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010365 mDispatcher->onWindowInfosChanged(
10366 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010367
10368 touch();
10369
10370 mTouchWindow->assertNoEvents();
10371}
10372
10373/**
10374 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
10375 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
10376 * (which alone would result in allowing touches) does not affect the blocking behavior.
10377 */
10378TEST_F(InputDispatcherUntrustedTouchesTest,
10379 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
10380 const sp<FakeWindowHandle>& wB =
10381 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
10382 OPACITY_BELOW_THRESHOLD);
10383 const sp<FakeWindowHandle>& wC =
10384 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10385 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010386 mDispatcher->onWindowInfosChanged(
10387 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010388
10389 touch();
10390
10391 mTouchWindow->assertNoEvents();
10392}
10393
10394/**
10395 * This test is testing that a window from a different UID but with same application token doesn't
10396 * block the touch. Apps can share the application token for close UI collaboration for example.
10397 */
10398TEST_F(InputDispatcherUntrustedTouchesTest,
10399 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
10400 const sp<FakeWindowHandle>& w =
10401 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
10402 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010403 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010404
10405 touch();
10406
10407 mTouchWindow->consumeAnyMotionDown();
10408}
10409
arthurhungb89ccb02020-12-30 16:19:01 +080010410class InputDispatcherDragTests : public InputDispatcherTest {
10411protected:
10412 std::shared_ptr<FakeApplicationHandle> mApp;
10413 sp<FakeWindowHandle> mWindow;
10414 sp<FakeWindowHandle> mSecondWindow;
10415 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010416 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010417 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
10418 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +080010419
10420 void SetUp() override {
10421 InputDispatcherTest::SetUp();
10422 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010423 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080010424 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080010425
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010426 mSecondWindow =
10427 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080010428 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080010429
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010430 mSpyWindow =
10431 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010432 mSpyWindow->setSpy(true);
10433 mSpyWindow->setTrustedOverlay(true);
10434 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
10435
arthurhungb89ccb02020-12-30 16:19:01 +080010436 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010437 mDispatcher->onWindowInfosChanged(
10438 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
10439 {},
10440 0,
10441 0});
arthurhungb89ccb02020-12-30 16:19:01 +080010442 }
10443
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010444 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
10445 switch (fromSource) {
10446 case AINPUT_SOURCE_TOUCHSCREEN:
10447 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010448 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010449 ADISPLAY_ID_DEFAULT, {50, 50}))
10450 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10451 break;
10452 case AINPUT_SOURCE_STYLUS:
10453 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010454 injectMotionEvent(*mDispatcher,
10455 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10456 AINPUT_SOURCE_STYLUS)
10457 .buttonState(
10458 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
10459 .pointer(PointerBuilder(0, ToolType::STYLUS)
10460 .x(50)
10461 .y(50))
10462 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010463 break;
10464 case AINPUT_SOURCE_MOUSE:
10465 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010466 injectMotionEvent(*mDispatcher,
10467 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10468 AINPUT_SOURCE_MOUSE)
10469 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
10470 .pointer(PointerBuilder(MOUSE_POINTER_ID,
10471 ToolType::MOUSE)
10472 .x(50)
10473 .y(50))
10474 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010475 break;
10476 default:
10477 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
10478 }
arthurhungb89ccb02020-12-30 16:19:01 +080010479
10480 // Window should receive motion event.
10481 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010482 // Spy window should also receive motion event
10483 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000010484 }
10485
10486 // Start performing drag, we will create a drag window and transfer touch to it.
10487 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
10488 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010489 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +000010490 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010491 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +000010492 }
arthurhungb89ccb02020-12-30 16:19:01 +080010493
10494 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010495 mDragWindow =
10496 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010497 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010498 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
10499 *mWindow->getInfo(), *mSecondWindow->getInfo()},
10500 {},
10501 0,
10502 0});
arthurhungb89ccb02020-12-30 16:19:01 +080010503
10504 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +000010505 bool transferred =
10506 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +000010507 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +000010508 if (transferred) {
10509 mWindow->consumeMotionCancel();
10510 mDragWindow->consumeMotionDown();
10511 }
10512 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +080010513 }
10514};
10515
10516TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010517 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +080010518
10519 // Move on window.
10520 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010521 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010522 ADISPLAY_ID_DEFAULT, {50, 50}))
10523 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10524 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10525 mWindow->consumeDragEvent(false, 50, 50);
10526 mSecondWindow->assertNoEvents();
10527
10528 // Move to another window.
10529 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010530 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010531 ADISPLAY_ID_DEFAULT, {150, 50}))
10532 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10533 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10534 mWindow->consumeDragEvent(true, 150, 50);
10535 mSecondWindow->consumeDragEvent(false, 50, 50);
10536
10537 // Move back to original window.
10538 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010539 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010540 ADISPLAY_ID_DEFAULT, {50, 50}))
10541 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10542 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10543 mWindow->consumeDragEvent(false, 50, 50);
10544 mSecondWindow->consumeDragEvent(true, -50, 50);
10545
10546 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010547 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10548 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080010549 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10550 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10551 mWindow->assertNoEvents();
10552 mSecondWindow->assertNoEvents();
10553}
10554
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010555TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010556 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010557
10558 // No cancel event after drag start
10559 mSpyWindow->assertNoEvents();
10560
10561 const MotionEvent secondFingerDownEvent =
10562 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10563 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010564 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10565 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010566 .build();
10567 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010568 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010569 InputEventInjectionSync::WAIT_FOR_RESULT))
10570 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10571
10572 // Receives cancel for first pointer after next pointer down
10573 mSpyWindow->consumeMotionCancel();
10574 mSpyWindow->consumeMotionDown();
10575
10576 mSpyWindow->assertNoEvents();
10577}
10578
arthurhungf452d0b2021-01-06 00:19:52 +080010579TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010580 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +080010581
10582 // Move on window.
10583 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010584 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +080010585 ADISPLAY_ID_DEFAULT, {50, 50}))
10586 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10587 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10588 mWindow->consumeDragEvent(false, 50, 50);
10589 mSecondWindow->assertNoEvents();
10590
10591 // Move to another window.
10592 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010593 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +080010594 ADISPLAY_ID_DEFAULT, {150, 50}))
10595 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10596 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10597 mWindow->consumeDragEvent(true, 150, 50);
10598 mSecondWindow->consumeDragEvent(false, 50, 50);
10599
10600 // drop to another window.
10601 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010602 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +080010603 {150, 50}))
10604 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10605 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010606 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +080010607 mWindow->assertNoEvents();
10608 mSecondWindow->assertNoEvents();
10609}
10610
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010611TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
10612 startDrag();
10613
10614 // No cancel event after drag start
10615 mSpyWindow->assertNoEvents();
10616
10617 const MotionEvent secondFingerDownEvent =
10618 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10619 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10620 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10621 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10622 .build();
10623 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10624 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10625 InputEventInjectionSync::WAIT_FOR_RESULT))
10626 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10627
10628 // Receives cancel for first pointer after next pointer down
10629 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080010630 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010631 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
10632
10633 mSpyWindow->assertNoEvents();
10634
10635 // Spy window calls pilfer pointers
10636 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
10637 mDragWindow->assertNoEvents();
10638
10639 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010640 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010641 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10642 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
10643 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10644 .build();
10645 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010646 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010647 InputEventInjectionSync::WAIT_FOR_RESULT))
10648 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10649
10650 // Drag window should still receive the new event
10651 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
10652 mDragWindow->assertNoEvents();
10653}
10654
arthurhung6d4bed92021-03-17 11:59:33 +080010655TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010656 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +080010657
10658 // Move on window and keep button pressed.
10659 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010660 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010661 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10662 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010663 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010664 .build()))
10665 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10666 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10667 mWindow->consumeDragEvent(false, 50, 50);
10668 mSecondWindow->assertNoEvents();
10669
10670 // Move to another window and release button, expect to drop item.
10671 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010672 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010673 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10674 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010675 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010676 .build()))
10677 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10678 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10679 mWindow->assertNoEvents();
10680 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010681 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +080010682
10683 // nothing to the window.
10684 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010685 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010686 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
10687 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010688 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010689 .build()))
10690 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10691 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10692 mWindow->assertNoEvents();
10693 mSecondWindow->assertNoEvents();
10694}
10695
Arthur Hung54745652022-04-20 07:17:41 +000010696TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010697 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +080010698
10699 // Set second window invisible.
10700 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010701 mDispatcher->onWindowInfosChanged(
10702 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +080010703
10704 // Move on window.
10705 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010706 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010707 ADISPLAY_ID_DEFAULT, {50, 50}))
10708 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10709 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10710 mWindow->consumeDragEvent(false, 50, 50);
10711 mSecondWindow->assertNoEvents();
10712
10713 // Move to another window.
10714 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010715 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010716 ADISPLAY_ID_DEFAULT, {150, 50}))
10717 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10718 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10719 mWindow->consumeDragEvent(true, 150, 50);
10720 mSecondWindow->assertNoEvents();
10721
10722 // drop to another window.
10723 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010724 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010725 {150, 50}))
10726 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10727 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010728 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010729 mWindow->assertNoEvents();
10730 mSecondWindow->assertNoEvents();
10731}
10732
Arthur Hung54745652022-04-20 07:17:41 +000010733TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010734 // Ensure window could track pointerIds if it didn't support split touch.
10735 mWindow->setPreventSplitting(true);
10736
Arthur Hung54745652022-04-20 07:17:41 +000010737 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010738 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010739 {50, 50}))
10740 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10741 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10742
10743 const MotionEvent secondFingerDownEvent =
10744 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10745 .displayId(ADISPLAY_ID_DEFAULT)
10746 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010747 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10748 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010749 .build();
10750 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010751 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010752 InputEventInjectionSync::WAIT_FOR_RESULT))
10753 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010754 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +000010755
10756 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010757 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010758}
10759
10760TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
10761 // First down on second window.
10762 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010763 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010764 {150, 50}))
10765 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10766
10767 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10768
10769 // Second down on first window.
10770 const MotionEvent secondFingerDownEvent =
10771 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10772 .displayId(ADISPLAY_ID_DEFAULT)
10773 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010774 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10775 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010776 .build();
10777 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010778 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010779 InputEventInjectionSync::WAIT_FOR_RESULT))
10780 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10781 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10782
10783 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010784 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010785
10786 // Move on window.
10787 const MotionEvent secondFingerMoveEvent =
10788 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10789 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010790 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10791 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010792 .build();
10793 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010794 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010795 InputEventInjectionSync::WAIT_FOR_RESULT));
10796 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10797 mWindow->consumeDragEvent(false, 50, 50);
10798 mSecondWindow->consumeMotionMove();
10799
10800 // Release the drag pointer should perform drop.
10801 const MotionEvent secondFingerUpEvent =
10802 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10803 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010804 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10805 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010806 .build();
10807 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010808 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010809 InputEventInjectionSync::WAIT_FOR_RESULT));
10810 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010811 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000010812 mWindow->assertNoEvents();
10813 mSecondWindow->consumeMotionMove();
10814}
10815
Arthur Hung3915c1f2022-05-31 07:17:17 +000010816TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010817 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000010818
10819 // Update window of second display.
10820 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010821 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010822 mDispatcher->onWindowInfosChanged(
10823 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10824 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10825 {},
10826 0,
10827 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010828
10829 // Let second display has a touch state.
10830 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010831 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010832 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10833 AINPUT_SOURCE_TOUCHSCREEN)
10834 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010835 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000010836 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000010837 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010838 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010839 mDispatcher->onWindowInfosChanged(
10840 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10841 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10842 {},
10843 0,
10844 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010845
10846 // Move on window.
10847 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010848 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010849 ADISPLAY_ID_DEFAULT, {50, 50}))
10850 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10851 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10852 mWindow->consumeDragEvent(false, 50, 50);
10853 mSecondWindow->assertNoEvents();
10854
10855 // Move to another window.
10856 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010857 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010858 ADISPLAY_ID_DEFAULT, {150, 50}))
10859 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10860 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10861 mWindow->consumeDragEvent(true, 150, 50);
10862 mSecondWindow->consumeDragEvent(false, 50, 50);
10863
10864 // drop to another window.
10865 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010866 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010867 {150, 50}))
10868 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10869 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010870 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000010871 mWindow->assertNoEvents();
10872 mSecondWindow->assertNoEvents();
10873}
10874
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010875TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
10876 startDrag(true, AINPUT_SOURCE_MOUSE);
10877 // Move on window.
10878 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010879 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010880 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10881 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010882 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010883 .x(50)
10884 .y(50))
10885 .build()))
10886 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10887 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10888 mWindow->consumeDragEvent(false, 50, 50);
10889 mSecondWindow->assertNoEvents();
10890
10891 // Move to another window.
10892 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010893 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010894 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10895 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010896 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010897 .x(150)
10898 .y(50))
10899 .build()))
10900 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10901 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10902 mWindow->consumeDragEvent(true, 150, 50);
10903 mSecondWindow->consumeDragEvent(false, 50, 50);
10904
10905 // drop to another window.
10906 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010907 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010908 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
10909 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010910 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010911 .x(150)
10912 .y(50))
10913 .build()))
10914 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10915 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010916 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010917 mWindow->assertNoEvents();
10918 mSecondWindow->assertNoEvents();
10919}
10920
Linnan Li5af92f92023-07-14 14:36:22 +080010921/**
10922 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
10923 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
10924 */
10925TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
10926 // Down on second window
10927 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10928 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10929 {150, 50}))
10930 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10931
10932 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
10933 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
10934
10935 // Down on first window
10936 const MotionEvent secondFingerDownEvent =
10937 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10938 .displayId(ADISPLAY_ID_DEFAULT)
10939 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10940 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10941 .build();
10942 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10943 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10944 InputEventInjectionSync::WAIT_FOR_RESULT))
10945 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10946 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10947 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
10948 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
10949
10950 // Start drag on first window
10951 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
10952
10953 // Trigger cancel
10954 mDispatcher->cancelCurrentTouch();
10955 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
10956 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
10957 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
10958
10959 ASSERT_TRUE(mDispatcher->waitForIdle());
10960 // The D&D finished with nullptr
10961 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
10962
10963 // Remove drag window
10964 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
10965
10966 // Inject a simple gesture, ensure dispatcher not crashed
10967 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10968 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10969 PointF{50, 50}))
10970 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10971 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10972
10973 const MotionEvent moveEvent =
10974 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10975 .displayId(ADISPLAY_ID_DEFAULT)
10976 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10977 .build();
10978 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10979 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
10980 InputEventInjectionSync::WAIT_FOR_RESULT))
10981 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10982 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
10983
10984 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10985 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10986 {50, 50}))
10987 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10988 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
10989}
10990
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000010991TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
10992 // Start hovering over the window.
10993 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10994 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
10995 ADISPLAY_ID_DEFAULT, {50, 50}));
10996
10997 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10998 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10999
11000 ASSERT_FALSE(startDrag(/*sendDown=*/false))
11001 << "Drag and drop should not work with a hovering pointer";
11002}
11003
Vishnu Nair062a8672021-09-03 16:07:44 -070011004class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
11005
11006TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
11007 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011008 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
11009 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011010 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011011 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
11012 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011013 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011014 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011015 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011016
11017 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000011018 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011019 window->assertNoEvents();
11020
Prabir Pradhan678438e2023-04-13 19:32:51 +000011021 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11022 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070011023 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
11024 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080011025 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070011026 window->assertNoEvents();
11027
11028 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011029 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011030 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011031
Prabir Pradhan678438e2023-04-13 19:32:51 +000011032 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011033 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
11034
Prabir Pradhan678438e2023-04-13 19:32:51 +000011035 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11036 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011037 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11038 window->assertNoEvents();
11039}
11040
11041TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
11042 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
11043 std::make_shared<FakeApplicationHandle>();
11044 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011045 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
11046 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070011047 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011048 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011049 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070011050 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011051 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
11052 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011053 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011054 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070011055 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
11056 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011057 mDispatcher->onWindowInfosChanged(
11058 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011059 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011060 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011061
11062 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000011063 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011064 window->assertNoEvents();
11065
Prabir Pradhan678438e2023-04-13 19:32:51 +000011066 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11067 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070011068 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
11069 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011070 window->assertNoEvents();
11071
11072 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011073 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011074 mDispatcher->onWindowInfosChanged(
11075 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011076
Prabir Pradhan678438e2023-04-13 19:32:51 +000011077 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011078 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
11079
Prabir Pradhan678438e2023-04-13 19:32:51 +000011080 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11081 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011082 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
11083 window->assertNoEvents();
11084}
11085
11086TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
11087 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
11088 std::make_shared<FakeApplicationHandle>();
11089 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011090 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
11091 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070011092 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011093 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011094 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070011095 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011096 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
11097 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011098 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011099 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070011100 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
11101 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011102 mDispatcher->onWindowInfosChanged(
11103 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011104 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011105 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011106
11107 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000011108 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011109 window->assertNoEvents();
11110
Prabir Pradhan678438e2023-04-13 19:32:51 +000011111 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11112 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070011113 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
11114 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011115 window->assertNoEvents();
11116
11117 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011118 mDispatcher->onWindowInfosChanged(
11119 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011120
Prabir Pradhan678438e2023-04-13 19:32:51 +000011121 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011122 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
11123
Prabir Pradhan678438e2023-04-13 19:32:51 +000011124 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11125 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011126 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11127 window->assertNoEvents();
11128}
11129
Antonio Kantekf16f2832021-09-28 04:39:20 +000011130class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
11131protected:
11132 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000011133 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000011134 sp<FakeWindowHandle> mWindow;
11135 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000011136 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000011137
11138 void SetUp() override {
11139 InputDispatcherTest::SetUp();
11140
11141 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000011142 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011143 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011144 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011145 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011146 mSecondWindow =
11147 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011148 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000011149 mThirdWindow =
11150 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
11151 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
11152 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011153
11154 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011155 mDispatcher->onWindowInfosChanged(
11156 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
11157 {},
11158 0,
11159 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000011160 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011161 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011162
Antonio Kantek15beb512022-06-13 22:35:41 +000011163 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000011164 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000011165 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070011166 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
11167 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000011168 mThirdWindow->assertNoEvents();
11169 }
11170
11171 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
11172 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000011173 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000011174 SECOND_DISPLAY_ID)) {
11175 mWindow->assertNoEvents();
11176 mSecondWindow->assertNoEvents();
11177 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070011178 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000011179 }
11180
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011181 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000011182 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070011183 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
11184 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000011185 mWindow->consumeTouchModeEvent(inTouchMode);
11186 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000011187 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000011188 }
11189};
11190
Antonio Kantek26defcf2022-02-08 01:12:27 +000011191TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080011192 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000011193 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
11194 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011195 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011196}
11197
Antonio Kantek26defcf2022-02-08 01:12:27 +000011198TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
11199 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011200 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011201 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011202 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011203 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000011204 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -070011205 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000011206 mWindow->assertNoEvents();
11207 mSecondWindow->assertNoEvents();
11208}
11209
11210TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
11211 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011212 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011213 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011214 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000011215 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000011216 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011217}
11218
Antonio Kantekf16f2832021-09-28 04:39:20 +000011219TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080011220 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000011221 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
11222 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011223 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000011224 mWindow->assertNoEvents();
11225 mSecondWindow->assertNoEvents();
11226}
11227
Antonio Kantek15beb512022-06-13 22:35:41 +000011228TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
11229 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
11230 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
11231 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011232 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000011233 mWindow->assertNoEvents();
11234 mSecondWindow->assertNoEvents();
11235 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
11236}
11237
Antonio Kantek48710e42022-03-24 14:19:30 -070011238TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
11239 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011240 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11241 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070011242 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11243 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
11244
11245 // Then remove focus.
11246 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011247 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070011248
11249 // Assert that caller can switch touch mode by owning one of the last interacted window.
11250 const WindowInfo& windowInfo = *mWindow->getInfo();
11251 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
11252 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011253 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070011254}
11255
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011256class InputDispatcherSpyWindowTest : public InputDispatcherTest {
11257public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011258 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011259 std::shared_ptr<FakeApplicationHandle> application =
11260 std::make_shared<FakeApplicationHandle>();
11261 std::string name = "Fake Spy ";
11262 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011263 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
11264 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011265 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011266 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011267 return spy;
11268 }
11269
11270 sp<FakeWindowHandle> createForeground() {
11271 std::shared_ptr<FakeApplicationHandle> application =
11272 std::make_shared<FakeApplicationHandle>();
11273 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011274 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
11275 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011276 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011277 return window;
11278 }
11279
11280private:
11281 int mSpyCount{0};
11282};
11283
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011284using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011285/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011286 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
11287 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011288TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070011289 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011290 ScopedSilentDeath _silentDeath;
11291
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011292 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011293 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011294 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011295 ".* not a trusted overlay");
11296}
11297
11298/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011299 * Input injection into a display with a spy window but no foreground windows should succeed.
11300 */
11301TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011302 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011303 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011304
11305 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011306 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011307 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11308 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11309}
11310
11311/**
11312 * Verify the order in which different input windows receive events. The touched foreground window
11313 * (if there is one) should always receive the event first. When there are multiple spy windows, the
11314 * spy windows will receive the event according to their Z-order, where the top-most spy window will
11315 * receive events before ones belows it.
11316 *
11317 * Here, we set up a scenario with four windows in the following Z order from the top:
11318 * spy1, spy2, window, spy3.
11319 * We then inject an event and verify that the foreground "window" receives it first, followed by
11320 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
11321 * window.
11322 */
11323TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
11324 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011325 auto spy1 = createSpy();
11326 auto spy2 = createSpy();
11327 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011328 mDispatcher->onWindowInfosChanged(
11329 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011330 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
11331 const size_t numChannels = channels.size();
11332
Michael Wright8e9a8562022-02-09 13:44:29 +000011333 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011334 if (!epollFd.ok()) {
11335 FAIL() << "Failed to create epoll fd";
11336 }
11337
11338 for (size_t i = 0; i < numChannels; i++) {
11339 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
11340 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
11341 FAIL() << "Failed to add fd to epoll";
11342 }
11343 }
11344
11345 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011346 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011347 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11348
11349 std::vector<size_t> eventOrder;
11350 std::vector<struct epoll_event> events(numChannels);
11351 for (;;) {
11352 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
11353 (100ms).count());
11354 if (nFds < 0) {
11355 FAIL() << "Failed to call epoll_wait";
11356 }
11357 if (nFds == 0) {
11358 break; // epoll_wait timed out
11359 }
11360 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070011361 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070011362 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011363 channels[i]->consumeMotionDown();
11364 }
11365 }
11366
11367 // Verify the order in which the events were received.
11368 EXPECT_EQ(3u, eventOrder.size());
11369 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
11370 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
11371 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
11372}
11373
11374/**
11375 * A spy window using the NOT_TOUCHABLE flag does not receive events.
11376 */
11377TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
11378 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011379 auto spy = createSpy();
11380 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011381 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011382
11383 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011384 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011385 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11386 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11387 spy->assertNoEvents();
11388}
11389
11390/**
11391 * A spy window will only receive gestures that originate within its touchable region. Gestures that
11392 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
11393 * to the window.
11394 */
11395TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
11396 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011397 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011398 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011399 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011400
11401 // Inject an event outside the spy window's touchable region.
11402 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011403 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011404 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11405 window->consumeMotionDown();
11406 spy->assertNoEvents();
11407 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011408 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011409 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11410 window->consumeMotionUp();
11411 spy->assertNoEvents();
11412
11413 // Inject an event inside the spy window's touchable region.
11414 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011415 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011416 {5, 10}))
11417 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11418 window->consumeMotionDown();
11419 spy->consumeMotionDown();
11420}
11421
11422/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011423 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011424 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011425 */
11426TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
11427 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011428 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011429 auto spy = createSpy();
11430 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011431 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011432 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011433 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011434
11435 // Inject an event outside the spy window's frame and touchable region.
11436 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011437 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011438 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011439 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11440 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011441 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011442}
11443
11444/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011445 * Even when a spy window spans over multiple foreground windows, the spy should receive all
11446 * pointers that are down within its bounds.
11447 */
11448TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
11449 auto windowLeft = createForeground();
11450 windowLeft->setFrame({0, 0, 100, 200});
11451 auto windowRight = createForeground();
11452 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011453 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011454 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011455 mDispatcher->onWindowInfosChanged(
11456 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011457
11458 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011459 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011460 {50, 50}))
11461 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11462 windowLeft->consumeMotionDown();
11463 spy->consumeMotionDown();
11464
11465 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011466 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011467 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011468 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11469 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011470 .build();
11471 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011472 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011473 InputEventInjectionSync::WAIT_FOR_RESULT))
11474 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11475 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000011476 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011477}
11478
11479/**
11480 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
11481 * the spy should receive the second pointer with ACTION_DOWN.
11482 */
11483TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
11484 auto window = createForeground();
11485 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011486 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011487 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011488 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011489
11490 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011491 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011492 {50, 50}))
11493 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11494 window->consumeMotionDown();
11495 spyRight->assertNoEvents();
11496
11497 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011498 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011499 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011500 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11501 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011502 .build();
11503 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011504 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011505 InputEventInjectionSync::WAIT_FOR_RESULT))
11506 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000011507 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011508 spyRight->consumeMotionDown();
11509}
11510
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011511/**
11512 * The spy window should not be able to affect whether or not touches are split. Only the foreground
11513 * windows should be allowed to control split touch.
11514 */
11515TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080011516 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011517 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011518 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080011519 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011520
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011521 auto window = createForeground();
11522 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011523
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011524 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011525
11526 // First finger down, no window touched.
11527 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011528 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011529 {100, 200}))
11530 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11531 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11532 window->assertNoEvents();
11533
11534 // Second finger down on window, the window should receive touch down.
11535 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011536 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011537 .displayId(ADISPLAY_ID_DEFAULT)
11538 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011539 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11540 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011541 .build();
11542 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011543 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011544 InputEventInjectionSync::WAIT_FOR_RESULT))
11545 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11546
11547 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000011548 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011549}
11550
11551/**
11552 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
11553 * do not receive key events.
11554 */
11555TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011556 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011557 spy->setFocusable(false);
11558
11559 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011560 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011561 setFocusedWindow(window);
11562 window->consumeFocusEvent(true);
11563
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011564 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011565 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11566 window->consumeKeyDown(ADISPLAY_ID_NONE);
11567
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011568 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011569 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11570 window->consumeKeyUp(ADISPLAY_ID_NONE);
11571
11572 spy->assertNoEvents();
11573}
11574
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011575using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
11576
11577/**
11578 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
11579 * are currently sent to any other windows - including other spy windows - will also be cancelled.
11580 */
11581TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
11582 auto window = createForeground();
11583 auto spy1 = createSpy();
11584 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011585 mDispatcher->onWindowInfosChanged(
11586 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011587
11588 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011589 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011590 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11591 window->consumeMotionDown();
11592 spy1->consumeMotionDown();
11593 spy2->consumeMotionDown();
11594
11595 // Pilfer pointers from the second spy window.
11596 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
11597 spy2->assertNoEvents();
11598 spy1->consumeMotionCancel();
11599 window->consumeMotionCancel();
11600
11601 // The rest of the gesture should only be sent to the second spy window.
11602 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011603 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011604 ADISPLAY_ID_DEFAULT))
11605 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11606 spy2->consumeMotionMove();
11607 spy1->assertNoEvents();
11608 window->assertNoEvents();
11609}
11610
11611/**
11612 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
11613 * in the middle of the gesture.
11614 */
11615TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
11616 auto window = createForeground();
11617 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011618 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011619
11620 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011621 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011622 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11623 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11624 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11625
11626 window->releaseChannel();
11627
11628 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11629
11630 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011631 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011632 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11633 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
11634}
11635
11636/**
11637 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
11638 * the spy, but not to any other windows.
11639 */
11640TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
11641 auto spy = createSpy();
11642 auto window = createForeground();
11643
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011644 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011645
11646 // First finger down on the window and the spy.
11647 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011648 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011649 {100, 200}))
11650 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11651 spy->consumeMotionDown();
11652 window->consumeMotionDown();
11653
11654 // Spy window pilfers the pointers.
11655 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11656 window->consumeMotionCancel();
11657
11658 // Second finger down on the window and spy, but the window should not receive the pointer down.
11659 const MotionEvent secondFingerDownEvent =
11660 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11661 .displayId(ADISPLAY_ID_DEFAULT)
11662 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011663 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11664 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011665 .build();
11666 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011667 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011668 InputEventInjectionSync::WAIT_FOR_RESULT))
11669 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11670
Harry Cutts33476232023-01-30 19:57:29 +000011671 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011672
11673 // Third finger goes down outside all windows, so injection should fail.
11674 const MotionEvent thirdFingerDownEvent =
11675 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11676 .displayId(ADISPLAY_ID_DEFAULT)
11677 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011678 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11679 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
11680 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011681 .build();
11682 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011683 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011684 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080011685 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011686
11687 spy->assertNoEvents();
11688 window->assertNoEvents();
11689}
11690
11691/**
11692 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
11693 */
11694TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
11695 auto spy = createSpy();
11696 spy->setFrame(Rect(0, 0, 100, 100));
11697 auto window = createForeground();
11698 window->setFrame(Rect(0, 0, 200, 200));
11699
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011700 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011701
11702 // First finger down on the window only
11703 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011704 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011705 {150, 150}))
11706 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11707 window->consumeMotionDown();
11708
11709 // Second finger down on the spy and window
11710 const MotionEvent secondFingerDownEvent =
11711 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11712 .displayId(ADISPLAY_ID_DEFAULT)
11713 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011714 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11715 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011716 .build();
11717 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011718 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011719 InputEventInjectionSync::WAIT_FOR_RESULT))
11720 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11721 spy->consumeMotionDown();
11722 window->consumeMotionPointerDown(1);
11723
11724 // Third finger down on the spy and window
11725 const MotionEvent thirdFingerDownEvent =
11726 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11727 .displayId(ADISPLAY_ID_DEFAULT)
11728 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011729 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11730 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
11731 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011732 .build();
11733 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011734 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011735 InputEventInjectionSync::WAIT_FOR_RESULT))
11736 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11737 spy->consumeMotionPointerDown(1);
11738 window->consumeMotionPointerDown(2);
11739
11740 // Spy window pilfers the pointers.
11741 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000011742 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
11743 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011744
11745 spy->assertNoEvents();
11746 window->assertNoEvents();
11747}
11748
11749/**
11750 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
11751 * other windows should be canceled. If this results in the cancellation of all pointers for some
11752 * window, then that window should receive ACTION_CANCEL.
11753 */
11754TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
11755 auto spy = createSpy();
11756 spy->setFrame(Rect(0, 0, 100, 100));
11757 auto window = createForeground();
11758 window->setFrame(Rect(0, 0, 200, 200));
11759
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011760 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011761
11762 // First finger down on both spy and window
11763 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011764 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011765 {10, 10}))
11766 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11767 window->consumeMotionDown();
11768 spy->consumeMotionDown();
11769
11770 // Second finger down on the spy and window
11771 const MotionEvent secondFingerDownEvent =
11772 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11773 .displayId(ADISPLAY_ID_DEFAULT)
11774 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011775 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11776 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011777 .build();
11778 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011779 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011780 InputEventInjectionSync::WAIT_FOR_RESULT))
11781 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11782 spy->consumeMotionPointerDown(1);
11783 window->consumeMotionPointerDown(1);
11784
11785 // Spy window pilfers the pointers.
11786 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11787 window->consumeMotionCancel();
11788
11789 spy->assertNoEvents();
11790 window->assertNoEvents();
11791}
11792
11793/**
11794 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
11795 * be sent to other windows
11796 */
11797TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
11798 auto spy = createSpy();
11799 spy->setFrame(Rect(0, 0, 100, 100));
11800 auto window = createForeground();
11801 window->setFrame(Rect(0, 0, 200, 200));
11802
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011803 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011804
11805 // First finger down on both window and spy
11806 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011807 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011808 {10, 10}))
11809 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11810 window->consumeMotionDown();
11811 spy->consumeMotionDown();
11812
11813 // Spy window pilfers the pointers.
11814 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11815 window->consumeMotionCancel();
11816
11817 // Second finger down on the window only
11818 const MotionEvent secondFingerDownEvent =
11819 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11820 .displayId(ADISPLAY_ID_DEFAULT)
11821 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011822 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11823 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011824 .build();
11825 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011826 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011827 InputEventInjectionSync::WAIT_FOR_RESULT))
11828 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11829 window->consumeMotionDown();
11830 window->assertNoEvents();
11831
11832 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
11833 spy->consumeMotionMove();
11834 spy->assertNoEvents();
11835}
11836
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011837/**
11838 * A window on the left and a window on the right. Also, a spy window that's above all of the
11839 * windows, and spanning both left and right windows.
11840 * Send simultaneous motion streams from two different devices, one to the left window, and another
11841 * to the right window.
11842 * Pilfer from spy window.
11843 * Check that the pilfering only affects the pointers that are actually being received by the spy.
11844 */
11845TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
11846 sp<FakeWindowHandle> spy = createSpy();
11847 spy->setFrame(Rect(0, 0, 200, 200));
11848 sp<FakeWindowHandle> leftWindow = createForeground();
11849 leftWindow->setFrame(Rect(0, 0, 100, 100));
11850
11851 sp<FakeWindowHandle> rightWindow = createForeground();
11852 rightWindow->setFrame(Rect(100, 0, 200, 100));
11853
11854 constexpr int32_t stylusDeviceId = 1;
11855 constexpr int32_t touchDeviceId = 2;
11856
11857 mDispatcher->onWindowInfosChanged(
11858 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
11859
11860 // Stylus down on left window and spy
11861 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
11862 .deviceId(stylusDeviceId)
11863 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
11864 .build());
11865 leftWindow->consumeMotionEvent(
11866 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11867 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11868
11869 // Finger down on right window and spy - but spy already has stylus
11870 mDispatcher->notifyMotion(
11871 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11872 .deviceId(touchDeviceId)
11873 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
11874 .build());
11875 rightWindow->consumeMotionEvent(
11876 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011877 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011878
11879 // Act: pilfer from spy. Spy is currently receiving touch events.
11880 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011881 leftWindow->consumeMotionEvent(
11882 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011883 rightWindow->consumeMotionEvent(
11884 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
11885
11886 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
11887 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
11888 .deviceId(stylusDeviceId)
11889 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
11890 .build());
11891 mDispatcher->notifyMotion(
11892 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
11893 .deviceId(touchDeviceId)
11894 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
11895 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011896 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011897
11898 spy->assertNoEvents();
11899 leftWindow->assertNoEvents();
11900 rightWindow->assertNoEvents();
11901}
11902
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000011903TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
11904 auto window = createForeground();
11905 auto spy = createSpy();
11906 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
11907
11908 mDispatcher->notifyMotion(
11909 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11910 .deviceId(1)
11911 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
11912 .build());
11913 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11914 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11915
11916 // Pilfer pointers from the spy window should fail.
11917 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
11918 spy->assertNoEvents();
11919 window->assertNoEvents();
11920}
11921
Prabir Pradhand65552b2021-10-07 11:23:50 -070011922class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
11923public:
11924 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
11925 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11926 std::make_shared<FakeApplicationHandle>();
11927 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011928 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11929 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011930 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011931 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011932 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011933 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011934 overlay->setTrustedOverlay(true);
11935
11936 std::shared_ptr<FakeApplicationHandle> application =
11937 std::make_shared<FakeApplicationHandle>();
11938 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011939 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
11940 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011941 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011942 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011943
11944 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011945 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011946 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011947 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011948 return {std::move(overlay), std::move(window)};
11949 }
11950
11951 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011952 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070011953 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000011954 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070011955 }
11956
11957 void sendStylusEvent(int32_t action) {
11958 NotifyMotionArgs motionArgs =
11959 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
11960 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011961 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000011962 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011963 }
11964};
11965
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011966using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
11967
11968TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070011969 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011970 ScopedSilentDeath _silentDeath;
11971
Prabir Pradhand65552b2021-10-07 11:23:50 -070011972 auto [overlay, window] = setupStylusOverlayScenario();
11973 overlay->setTrustedOverlay(false);
11974 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011975 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
11976 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070011977 ".* not a trusted overlay");
11978}
11979
11980TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
11981 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011982 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011983
11984 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11985 overlay->consumeMotionDown();
11986 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11987 overlay->consumeMotionUp();
11988
11989 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11990 window->consumeMotionDown();
11991 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11992 window->consumeMotionUp();
11993
11994 overlay->assertNoEvents();
11995 window->assertNoEvents();
11996}
11997
11998TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
11999 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012000 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012001 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070012002
12003 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
12004 overlay->consumeMotionDown();
12005 window->consumeMotionDown();
12006 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
12007 overlay->consumeMotionUp();
12008 window->consumeMotionUp();
12009
12010 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
12011 window->consumeMotionDown();
12012 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
12013 window->consumeMotionUp();
12014
12015 overlay->assertNoEvents();
12016 window->assertNoEvents();
12017}
12018
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000012019/**
12020 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
12021 * The scenario is as follows:
12022 * - The stylus interceptor overlay is configured as a spy window.
12023 * - The stylus interceptor spy receives the start of a new stylus gesture.
12024 * - It pilfers pointers and then configures itself to no longer be a spy.
12025 * - The stylus interceptor continues to receive the rest of the gesture.
12026 */
12027TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
12028 auto [overlay, window] = setupStylusOverlayScenario();
12029 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012030 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000012031
12032 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
12033 overlay->consumeMotionDown();
12034 window->consumeMotionDown();
12035
12036 // The interceptor pilfers the pointers.
12037 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
12038 window->consumeMotionCancel();
12039
12040 // The interceptor configures itself so that it is no longer a spy.
12041 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012042 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000012043
12044 // It continues to receive the rest of the stylus gesture.
12045 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
12046 overlay->consumeMotionMove();
12047 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
12048 overlay->consumeMotionUp();
12049
12050 window->assertNoEvents();
12051}
12052
Prabir Pradhan5735a322022-04-11 17:23:34 +000012053struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012054 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000012055 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000012056 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
12057 std::unique_ptr<InputDispatcher>& mDispatcher;
12058
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012059 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000012060 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
12061
12062 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012063 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000012064 ADISPLAY_ID_DEFAULT, {100, 200},
12065 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
12066 AMOTION_EVENT_INVALID_CURSOR_POSITION},
12067 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
12068 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
12069 }
12070
12071 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012072 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000012073 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000012074 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000012075 mPolicyFlags);
12076 }
12077
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012078 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000012079 std::shared_ptr<FakeApplicationHandle> overlayApplication =
12080 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012081 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
12082 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000012083 window->setOwnerInfo(mPid, mUid);
12084 return window;
12085 }
12086};
12087
12088using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
12089
12090TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012091 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012092 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012093 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012094
12095 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12096 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12097 window->consumeMotionDown();
12098
12099 setFocusedWindow(window);
12100 window->consumeFocusEvent(true);
12101
12102 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12103 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
12104 window->consumeKeyDown(ADISPLAY_ID_NONE);
12105}
12106
12107TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012108 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012109 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012110 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012111
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012112 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012113 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
12114 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12115
12116 setFocusedWindow(window);
12117 window->consumeFocusEvent(true);
12118
12119 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
12120 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
12121 window->assertNoEvents();
12122}
12123
12124TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012125 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012126 auto window = owner.createWindow("Owned window");
12127 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012128 spy->setSpy(true);
12129 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012130 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012131
12132 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12133 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12134 spy->consumeMotionDown();
12135 window->consumeMotionDown();
12136}
12137
12138TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012139 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012140 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012141
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012142 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012143 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012144 randosSpy->setSpy(true);
12145 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012146 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012147
12148 // The event is targeted at owner's window, so injection should succeed, but the spy should
12149 // not receive the event.
12150 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12151 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12152 randosSpy->assertNoEvents();
12153 window->consumeMotionDown();
12154}
12155
12156TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012157 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012158 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012159
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012160 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012161 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012162 randosSpy->setSpy(true);
12163 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012164 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012165
12166 // A user that has injection permission can inject into any window.
12167 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012168 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000012169 ADISPLAY_ID_DEFAULT));
12170 randosSpy->consumeMotionDown();
12171 window->consumeMotionDown();
12172
12173 setFocusedWindow(randosSpy);
12174 randosSpy->consumeFocusEvent(true);
12175
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012176 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000012177 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
12178 window->assertNoEvents();
12179}
12180
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012181TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012182 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012183 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012184
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012185 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012186 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012187 randosWindow->setFrame(Rect{-10, -10, -5, -5});
12188 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012189 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012190
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012191 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000012192 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12193 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12194 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012195 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000012196}
12197
Prabir Pradhan64f21d22023-11-28 21:19:42 +000012198using InputDispatcherPointerInWindowTest = InputDispatcherTest;
12199
12200TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
12201 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12202
12203 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12204 ADISPLAY_ID_DEFAULT);
12205 left->setFrame(Rect(0, 0, 100, 100));
12206 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12207 "Right Window", ADISPLAY_ID_DEFAULT);
12208 right->setFrame(Rect(100, 0, 200, 100));
12209 sp<FakeWindowHandle> spy =
12210 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
12211 spy->setFrame(Rect(0, 0, 200, 100));
12212 spy->setTrustedOverlay(true);
12213 spy->setSpy(true);
12214
12215 mDispatcher->onWindowInfosChanged(
12216 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
12217
12218 // Hover into the left window.
12219 mDispatcher->notifyMotion(
12220 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
12221 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
12222 .build());
12223
12224 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12225 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12226
12227 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12228 /*pointerId=*/0));
12229 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12230 /*pointerId=*/0));
12231 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12232 /*pointerId=*/0));
12233
12234 // Hover move to the right window.
12235 mDispatcher->notifyMotion(
12236 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
12237 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
12238 .build());
12239
12240 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12241 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12242 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
12243
12244 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12245 /*pointerId=*/0));
12246 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12247 /*pointerId=*/0));
12248 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12249 /*pointerId=*/0));
12250
12251 // Stop hovering.
12252 mDispatcher->notifyMotion(
12253 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
12254 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
12255 .build());
12256
12257 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12258 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12259
12260 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12261 /*pointerId=*/0));
12262 ASSERT_FALSE(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}
12267
12268TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
12269 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12270
12271 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12272 ADISPLAY_ID_DEFAULT);
12273 left->setFrame(Rect(0, 0, 100, 100));
12274 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12275 "Right Window", ADISPLAY_ID_DEFAULT);
12276 right->setFrame(Rect(100, 0, 200, 100));
12277 sp<FakeWindowHandle> spy =
12278 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
12279 spy->setFrame(Rect(0, 0, 200, 100));
12280 spy->setTrustedOverlay(true);
12281 spy->setSpy(true);
12282
12283 mDispatcher->onWindowInfosChanged(
12284 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
12285
12286 // First pointer down on left window.
12287 mDispatcher->notifyMotion(
12288 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12289 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12290 .build());
12291
12292 left->consumeMotionDown();
12293 spy->consumeMotionDown();
12294
12295 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12296 /*pointerId=*/0));
12297 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12298 /*pointerId=*/0));
12299 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12300 /*pointerId=*/0));
12301
12302 // Second pointer down on right window.
12303 mDispatcher->notifyMotion(
12304 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12305 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12306 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
12307 .build());
12308
12309 left->consumeMotionMove();
12310 right->consumeMotionDown();
12311 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
12312
12313 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12314 /*pointerId=*/0));
12315 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12316 /*pointerId=*/0));
12317 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12318 /*pointerId=*/0));
12319 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12320 /*pointerId=*/1));
12321 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12322 /*pointerId=*/1));
12323 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12324 /*pointerId=*/1));
12325
12326 // Second pointer up.
12327 mDispatcher->notifyMotion(
12328 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
12329 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12330 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
12331 .build());
12332
12333 left->consumeMotionMove();
12334 right->consumeMotionUp();
12335 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
12336
12337 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12338 /*pointerId=*/0));
12339 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12340 /*pointerId=*/0));
12341 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12342 /*pointerId=*/0));
12343 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12344 /*pointerId=*/1));
12345 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12346 /*pointerId=*/1));
12347 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12348 /*pointerId=*/1));
12349
12350 // First pointer up.
12351 mDispatcher->notifyMotion(
12352 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
12353 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12354 .build());
12355
12356 left->consumeMotionUp();
12357 spy->consumeMotionUp();
12358
12359 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12360 /*pointerId=*/0));
12361 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12362 /*pointerId=*/0));
12363 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12364 /*pointerId=*/0));
12365}
12366
12367TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
12368 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12369
12370 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12371 ADISPLAY_ID_DEFAULT);
12372 left->setFrame(Rect(0, 0, 100, 100));
12373 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12374 "Right Window", ADISPLAY_ID_DEFAULT);
12375 right->setFrame(Rect(100, 0, 200, 100));
12376
12377 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
12378
12379 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12380 /*pointerId=*/0));
12381 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12382 /*pointerId=*/0));
12383
12384 // Hover move into the window.
12385 mDispatcher->notifyMotion(
12386 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12387 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
12388 .rawXCursorPosition(50)
12389 .rawYCursorPosition(50)
12390 .deviceId(DEVICE_ID)
12391 .build());
12392
12393 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12394
12395 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12396 /*pointerId=*/0));
12397
12398 // Move the mouse with another device. This cancels the hovering pointer from the first device.
12399 mDispatcher->notifyMotion(
12400 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12401 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
12402 .rawXCursorPosition(51)
12403 .rawYCursorPosition(50)
12404 .deviceId(SECOND_DEVICE_ID)
12405 .build());
12406
12407 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12408 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12409
12410 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
12411 // a HOVER_EXIT from the first device.
12412 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12413 /*pointerId=*/0));
12414 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
12415 SECOND_DEVICE_ID,
12416 /*pointerId=*/0));
12417
12418 // Move the mouse outside the window. Document the current behavior, where the window does not
12419 // receive HOVER_EXIT even though the mouse left the window.
12420 mDispatcher->notifyMotion(
12421 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12422 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
12423 .rawXCursorPosition(150)
12424 .rawYCursorPosition(50)
12425 .deviceId(SECOND_DEVICE_ID)
12426 .build());
12427
12428 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12429 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12430 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12431 /*pointerId=*/0));
12432 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
12433 SECOND_DEVICE_ID,
12434 /*pointerId=*/0));
12435}
12436
Garfield Tane84e6f92019-08-29 17:28:41 -070012437} // namespace android::inputdispatcher