blob: dc13fed569673e13665f397a8462a5881736933a [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"
Siarhei Vishniakou2defec02023-06-08 17:24:44 -070018#include "FakeApplicationHandle.h"
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +000019#include "FakeInputTracingBackend.h"
Prabir Pradhane3b28dd2023-10-06 04:19:29 +000020#include "TestEventMatchers.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080021
Cody Heiner166a5af2023-07-07 12:25:00 -070022#include <NotifyArgsBuilders.h>
Prabir Pradhan5893d362023-11-17 04:30:40 +000023#include <android-base/logging.h>
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070024#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080025#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080026#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070027#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070028#include <binder/Binder.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000029#include <com_android_input_flags.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000030#include <fcntl.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000031#include <flag_macros.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080032#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080033#include <gtest/gtest.h>
Siarhei Vishniakou8c5f7be2024-05-01 22:48:16 +000034#include <input/BlockingQueue.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 }
Prabir Pradhanedd96402022-02-15 01:46:16 -0800173 };
174
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);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001280 if (event == nullptr) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001281 ADD_FAILURE() << "No event";
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001282 return nullptr;
1283 }
1284 if (event->getType() != InputEventType::KEY) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001285 ADD_FAILURE() << "Instead of key event, got " << event;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001286 return nullptr;
1287 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001288 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);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001294 ASSERT_THAT(*keyEvent, matcher);
1295 }
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
Siarhei Vishniakou9b849a72024-07-15 18:11:27 +00001343 inline void consumeMotionPointerDown(int32_t pointerIdx,
1344 const ::testing::Matcher<MotionEvent>& matcher) {
1345 const int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1346 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1347 consumeMotionEvent(testing::AllOf(WithMotionAction(action), matcher));
1348 }
1349
Svet Ganov5d3bc372020-01-26 23:11:07 -08001350 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001351 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001352 const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001353 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001354 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1355 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001356 }
1357
Siarhei Vishniakou9b849a72024-07-15 18:11:27 +00001358 inline void consumeMotionPointerUp(int32_t pointerIdx,
1359 const ::testing::Matcher<MotionEvent>& matcher) {
1360 const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1361 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1362 consumeMotionEvent(testing::AllOf(WithMotionAction(action), matcher));
1363 }
1364
Svet Ganov5d3bc372020-01-26 23:11:07 -08001365 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001366 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001367 consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1368 WithFlags(expectedFlags)));
Michael Wright3a240c42019-12-10 20:53:41 +00001369 }
1370
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001371 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1372 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001373 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE),
1374 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001375 }
1376
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001377 void consumeMotionOutsideWithZeroedCoords() {
1378 consumeMotionEvent(
1379 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE), WithRawCoords(0, 0)));
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001380 }
1381
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001382 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1383 ASSERT_NE(mInputReceiver, nullptr)
1384 << "Cannot consume events from a window with no receiver";
1385 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1386 }
1387
Prabir Pradhan99987712020-11-10 18:43:05 -08001388 void consumeCaptureEvent(bool hasCapture) {
1389 ASSERT_NE(mInputReceiver, nullptr)
1390 << "Cannot consume events from a window with no receiver";
1391 mInputReceiver->consumeCaptureEvent(hasCapture);
1392 }
1393
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001394 std::unique_ptr<MotionEvent> consumeMotionEvent(
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001395 const ::testing::Matcher<MotionEvent>& matcher = testing::_) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001396 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
1397 if (event == nullptr) {
1398 ADD_FAILURE() << "No event";
1399 return nullptr;
Prabir Pradhan5893d362023-11-17 04:30:40 +00001400 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001401 if (event->getType() != InputEventType::MOTION) {
1402 ADD_FAILURE() << "Instead of motion event, got " << *event;
1403 return nullptr;
1404 }
1405 std::unique_ptr<MotionEvent> motionEvent =
1406 std::unique_ptr<MotionEvent>(static_cast<MotionEvent*>(event.release()));
Prabir Pradhan5893d362023-11-17 04:30:40 +00001407 EXPECT_THAT(*motionEvent, matcher);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001408 return motionEvent;
chaviwd1c23182019-12-20 18:44:56 -08001409 }
1410
arthurhungb89ccb02020-12-30 16:19:01 +08001411 void consumeDragEvent(bool isExiting, float x, float y) {
1412 mInputReceiver->consumeDragEvent(isExiting, x, y);
1413 }
1414
Antonio Kantekf16f2832021-09-28 04:39:20 +00001415 void consumeTouchModeEvent(bool inTouchMode) {
1416 ASSERT_NE(mInputReceiver, nullptr)
1417 << "Cannot consume events from a window with no receiver";
1418 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1419 }
1420
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001421 std::pair<std::optional<uint32_t>, std::unique_ptr<InputEvent>> receiveEvent() {
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001422 return receive();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001423 }
1424
1425 void finishEvent(uint32_t sequenceNum) {
1426 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1427 mInputReceiver->finishEvent(sequenceNum);
1428 }
1429
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001430 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1431 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1432 mInputReceiver->sendTimeline(inputEventId, timeline);
1433 }
1434
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001435 void assertNoEvents(std::chrono::milliseconds timeout = CONSUME_TIMEOUT_NO_EVENT_EXPECTED) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001436 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001437 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001438 return; // Can't receive events if the window does not have input channel
1439 }
1440 ASSERT_NE(nullptr, mInputReceiver)
1441 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001442 mInputReceiver->assertNoEvents(timeout);
Arthur Hungb92218b2018-08-14 12:00:21 +08001443 }
1444
chaviwaf87b3e2019-10-01 16:59:28 -07001445 sp<IBinder> getToken() { return mInfo.token; }
1446
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001447 const std::string& getName() { return mName; }
1448
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001449 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001450 mInfo.ownerPid = ownerPid;
1451 mInfo.ownerUid = ownerUid;
1452 }
1453
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001454 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001455
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001456 void destroyReceiver() { mInputReceiver = nullptr; }
1457
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001458 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1459
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001460 // FakeWindowHandle uses this consume method to ensure received events are added to the trace.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001461 std::unique_ptr<InputEvent> consume(std::chrono::milliseconds timeout, bool handled = true) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001462 if (mInputReceiver == nullptr) {
1463 LOG(FATAL) << "Cannot consume event from a window with no input event receiver";
1464 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001465 std::unique_ptr<InputEvent> event = mInputReceiver->consume(timeout, handled);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001466 if (event == nullptr) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001467 ADD_FAILURE() << "Consume failed: no event";
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001468 }
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001469 expectReceivedEventTraced(event);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001470 return event;
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001471 }
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001472
chaviwd1c23182019-12-20 18:44:56 -08001473private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001474 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001475 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001476 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001477 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001478 friend class sp<FakeWindowHandle>;
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001479
1480 // FakeWindowHandle uses this receive method to ensure received events are added to the trace.
1481 std::pair<std::optional<uint32_t /*seq*/>, std::unique_ptr<InputEvent>> receive() {
1482 if (mInputReceiver == nullptr) {
1483 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1484 return std::make_pair(std::nullopt, nullptr);
1485 }
1486 auto out = mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1487 const auto& [_, event] = out;
1488 expectReceivedEventTraced(event);
1489 return std::move(out);
1490 }
1491
1492 void expectReceivedEventTraced(const std::unique_ptr<InputEvent>& event) {
1493 if (!event) {
1494 return;
1495 }
1496
1497 switch (event->getType()) {
1498 case InputEventType::KEY: {
Prabir Pradhan4497c862023-12-15 07:13:30 +00001499 gVerifyingTrace->expectKeyDispatchTraced(static_cast<KeyEvent&>(*event), mInfo.id);
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001500 break;
1501 }
1502 case InputEventType::MOTION: {
Prabir Pradhan4497c862023-12-15 07:13:30 +00001503 gVerifyingTrace->expectMotionDispatchTraced(static_cast<MotionEvent&>(*event),
1504 mInfo.id);
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001505 break;
1506 }
1507 default:
1508 break;
1509 }
1510 }
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001511};
1512
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001513std::atomic<int32_t> FakeWindowHandle::sId{1};
1514
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001515class FakeMonitorReceiver {
1516public:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001517 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId)
1518 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001519
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001520 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001521
1522 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001523 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1524 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001525 }
1526
1527 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001528 const auto [sequenceNum, _] = mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1529 return sequenceNum;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001530 }
1531
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001532 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001533
1534 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001535 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1536 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001537 }
1538
1539 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001540 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1541 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001542 }
1543
1544 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001545 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1546 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001547 }
1548
1549 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001550 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001551 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1552 WithDisplayId(expectedDisplayId),
1553 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1554 }
1555
1556 void consumeMotionPointerDown(int32_t pointerIdx) {
1557 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1558 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001559 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1560 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001561 }
1562
1563 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001564 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001565 }
1566
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001567 std::unique_ptr<MotionEvent> consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001568
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001569 void assertNoEvents() { mInputReceiver.assertNoEvents(CONSUME_TIMEOUT_NO_EVENT_EXPECTED); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001570
1571private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001572 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001573};
1574
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001575static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001576 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001577 int32_t displayId = ADISPLAY_ID_NONE,
1578 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001579 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001580 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001581 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001582 KeyEvent event;
1583 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1584
1585 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001586 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001587 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1588 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001589
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001590 if (!allowKeyRepeat) {
1591 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1592 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001593 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001594 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001595}
1596
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001597static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1598 InputEventInjectionResult result =
1599 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1600 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1601 if (result != InputEventInjectionResult::TIMED_OUT) {
1602 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1603 }
1604}
1605
1606static InputEventInjectionResult injectKeyDown(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_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001609}
1610
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001611// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1612// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1613// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001614static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1615 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001616 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001617 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001618 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001619}
1620
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001621static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001622 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001623 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001624}
1625
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001626static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001627 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001628 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001629 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001630 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001631 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1632 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001633}
1634
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001635static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001636 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1637 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001638 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001639 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1640 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001641 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001642 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001643 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001644 MotionEventBuilder motionBuilder =
1645 MotionEventBuilder(action, source)
1646 .displayId(displayId)
1647 .eventTime(eventTime)
1648 .rawXCursorPosition(cursorPosition.x)
1649 .rawYCursorPosition(cursorPosition.y)
1650 .pointer(
1651 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1652 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1653 motionBuilder.downTime(eventTime);
1654 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001655
1656 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001657 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1658 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001659}
1660
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001661static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1662 int32_t displayId,
1663 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001664 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001665}
1666
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001667static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1668 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001669 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001670 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001671}
1672
Jackal Guof9696682018-10-05 12:23:23 +08001673static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1674 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1675 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001676 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1677 AINPUT_SOURCE_KEYBOARD, displayId, POLICY_FLAG_PASS_TO_USER, action,
1678 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001679
1680 return args;
1681}
1682
Josep del Riob3981622023-04-18 15:49:45 +00001683static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1684 int32_t displayId = ADISPLAY_ID_NONE) {
1685 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1686 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001687 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1688 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C,
1689 AMETA_META_ON, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001690
1691 return args;
1692}
1693
1694static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1695 int32_t displayId = ADISPLAY_ID_NONE) {
1696 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1697 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001698 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1699 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST,
1700 KEY_ASSISTANT, AMETA_NONE, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001701
1702 return args;
1703}
1704
Prabir Pradhan678438e2023-04-13 19:32:51 +00001705[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1706 int32_t displayId,
1707 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001708 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001709 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1710 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1711 }
1712
chaviwd1c23182019-12-20 18:44:56 -08001713 PointerProperties pointerProperties[pointerCount];
1714 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001715
chaviwd1c23182019-12-20 18:44:56 -08001716 for (size_t i = 0; i < pointerCount; i++) {
1717 pointerProperties[i].clear();
1718 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001719 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001720
chaviwd1c23182019-12-20 18:44:56 -08001721 pointerCoords[i].clear();
1722 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1723 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1724 }
Jackal Guof9696682018-10-05 12:23:23 +08001725
1726 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1727 // Define a valid motion event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001728 NotifyMotionArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, source,
1729 displayId, POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0,
1730 /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001731 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001732 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001733 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001734 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001735
1736 return args;
1737}
1738
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001739static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1740 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1741}
1742
chaviwd1c23182019-12-20 18:44:56 -08001743static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1744 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1745}
1746
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001747static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1748 const PointerCaptureRequest& request) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001749 return NotifyPointerCaptureChangedArgs(InputEvent::nextId(), systemTime(SYSTEM_TIME_MONOTONIC),
1750 request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001751}
1752
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001753} // namespace
1754
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001755/**
1756 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1757 * broken channel.
1758 */
1759TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1760 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1761 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001762 sp<FakeWindowHandle>::make(application, mDispatcher,
1763 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001764
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001765 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001766
1767 // Window closes its channel, but the window remains.
1768 window->destroyReceiver();
1769 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1770}
1771
Arthur Hungb92218b2018-08-14 12:00:21 +08001772TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001773 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001774 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1775 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001776
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001777 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001778 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001779 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001780 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001781
1782 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001783 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001784}
1785
Siarhei Vishniakouaeed0da2024-01-09 08:57:13 -08001786using InputDispatcherDeathTest = InputDispatcherTest;
1787
1788/**
1789 * When 'onWindowInfosChanged' arguments contain a duplicate entry for the same window, dispatcher
1790 * should crash.
1791 */
1792TEST_F(InputDispatcherDeathTest, DuplicateWindowInfosAbortDispatcher) {
1793 testing::GTEST_FLAG(death_test_style) = "threadsafe";
1794 ScopedSilentDeath _silentDeath;
1795
1796 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1797 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1798 "Fake Window", ADISPLAY_ID_DEFAULT);
1799 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
1800 {{*window->getInfo(), *window->getInfo()}, {}, 0, 0}),
1801 "Incorrect WindowInfosUpdate provided");
1802}
1803
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001804TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1805 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001806 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1807 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001808
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001809 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001810 // Inject a MotionEvent to an unknown display.
1811 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001812 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001813 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1814
1815 // Window should receive motion event.
1816 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1817}
1818
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001819/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001820 * Calling onWindowInfosChanged once should not cause any issues.
1821 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001822 * called twice.
1823 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001824TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001825 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001826 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1827 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001828 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001829
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001830 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001831 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001832 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001833 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001834 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001835
1836 // Window should receive motion event.
1837 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1838}
1839
1840/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001841 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001842 */
1843TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001844 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001845 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1846 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001847 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001848
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001849 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1850 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001851 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001852 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001853 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001854 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001855
1856 // Window should receive motion event.
1857 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1858}
1859
Arthur Hungb92218b2018-08-14 12:00:21 +08001860// The foreground window should receive the first touch down event.
1861TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001862 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001863 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001864 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001865 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001866 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001867
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001868 mDispatcher->onWindowInfosChanged(
1869 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001870 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001871 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001872 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001873
1874 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001875 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001876 windowSecond->assertNoEvents();
1877}
1878
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001879/**
1880 * Two windows: A top window, and a wallpaper behind the window.
1881 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1882 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001883 * 1. foregroundWindow <-- dup touch to wallpaper
1884 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001885 */
1886TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1887 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1888 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001889 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001890 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001891 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001892 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001893 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001894
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001895 mDispatcher->onWindowInfosChanged(
1896 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001897 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001898 injectMotionEvent(*mDispatcher,
1899 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1900 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
1901 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001902 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1903
1904 // Both foreground window and its wallpaper should receive the touch down
1905 foregroundWindow->consumeMotionDown();
1906 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1907
1908 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001909 injectMotionEvent(*mDispatcher,
1910 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1911 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
1912 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001913 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1914
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001915 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001916 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1917
1918 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001919 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001920 foregroundWindow->consumeMotionCancel();
1921 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1922 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1923}
1924
1925/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001926 * Two fingers down on the window, and lift off the first finger.
1927 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1928 * contains a single pointer.
1929 */
1930TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1931 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1932 sp<FakeWindowHandle> window =
1933 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1934
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001935 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001936 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001937 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1938 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1939 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001940 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001941 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1942 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1943 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1944 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001945 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001946 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1947 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1948 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1949 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001950 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1951 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1952 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1953
1954 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001955 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001956 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1957 window->consumeMotionEvent(
1958 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1959}
1960
1961/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001962 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1963 * with the following differences:
1964 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1965 * clean up the connection.
1966 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1967 * Ensure that there's no crash in the dispatcher.
1968 */
1969TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1970 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1971 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001972 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001973 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001974 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001975 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001976 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001977
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001978 mDispatcher->onWindowInfosChanged(
1979 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001980 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001981 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001982 {100, 200}))
1983 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1984
1985 // Both foreground window and its wallpaper should receive the touch down
1986 foregroundWindow->consumeMotionDown();
1987 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1988
1989 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001990 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001991 ADISPLAY_ID_DEFAULT, {110, 200}))
1992 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1993
1994 foregroundWindow->consumeMotionMove();
1995 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1996
1997 // Wallpaper closes its channel, but the window remains.
1998 wallpaperWindow->destroyReceiver();
1999 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
2000
2001 // Now the foreground window goes away, but the wallpaper stays, even though its channel
2002 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002003 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08002004 foregroundWindow->consumeMotionCancel();
2005}
2006
Arthur Hungc539dbb2022-12-08 07:45:36 +00002007class ShouldSplitTouchFixture : public InputDispatcherTest,
2008 public ::testing::WithParamInterface<bool> {};
2009INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
2010 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08002011/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002012 * A single window that receives touch (on top), and a wallpaper window underneath it.
2013 * The top window gets a multitouch gesture.
2014 * Ensure that wallpaper gets the same gesture.
2015 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00002016TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002017 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002018 sp<FakeWindowHandle> foregroundWindow =
2019 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
2020 foregroundWindow->setDupTouchToWallpaper(true);
2021 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002022
2023 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002024 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002025 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002026
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002027 mDispatcher->onWindowInfosChanged(
2028 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002029
2030 // Touch down on top window
2031 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002032 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002033 {100, 100}))
2034 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2035
2036 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00002037 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002038 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2039
2040 // Second finger down on the top window
2041 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002042 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002043 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002044 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2045 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002046 .build();
2047 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002048 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002049 InputEventInjectionSync::WAIT_FOR_RESULT))
2050 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2051
Harry Cutts33476232023-01-30 19:57:29 +00002052 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
2053 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002054 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00002055
2056 const MotionEvent secondFingerUpEvent =
2057 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2058 .displayId(ADISPLAY_ID_DEFAULT)
2059 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002060 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2061 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002062 .build();
2063 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002064 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002065 InputEventInjectionSync::WAIT_FOR_RESULT))
2066 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2067 foregroundWindow->consumeMotionPointerUp(0);
2068 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2069
2070 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002071 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002072 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2073 AINPUT_SOURCE_TOUCHSCREEN)
2074 .displayId(ADISPLAY_ID_DEFAULT)
2075 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00002076 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002077 .x(100)
2078 .y(100))
2079 .build(),
2080 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002081 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2082 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2083 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002084}
2085
2086/**
2087 * Two windows: a window on the left and window on the right.
2088 * A third window, wallpaper, is behind both windows, and spans both top windows.
2089 * The first touch down goes to the left window. A second pointer touches down on the right window.
2090 * The touch is split, so both left and right windows should receive ACTION_DOWN.
2091 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
2092 * ACTION_POINTER_DOWN(1).
2093 */
2094TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
2095 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2096 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002097 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002098 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002099 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002100
2101 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002102 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002103 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002104 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002105
2106 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002107 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002108 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002109 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002110
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002111 mDispatcher->onWindowInfosChanged(
2112 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2113 {},
2114 0,
2115 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002116
2117 // Touch down on left window
2118 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002119 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002120 {100, 100}))
2121 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2122
2123 // Both foreground window and its wallpaper should receive the touch down
2124 leftWindow->consumeMotionDown();
2125 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2126
2127 // Second finger down on the right window
2128 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002129 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002130 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002131 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2132 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002133 .build();
2134 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002135 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002136 InputEventInjectionSync::WAIT_FOR_RESULT))
2137 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2138
2139 leftWindow->consumeMotionMove();
2140 // Since the touch is split, right window gets ACTION_DOWN
2141 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002142 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002143 expectedWallpaperFlags);
2144
2145 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002146 mDispatcher->onWindowInfosChanged(
2147 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002148 leftWindow->consumeMotionCancel();
2149 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2150 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2151
2152 // The pointer that's still down on the right window moves, and goes to the right window only.
2153 // As far as the dispatcher's concerned though, both pointers are still present.
2154 const MotionEvent secondFingerMoveEvent =
2155 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2156 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002157 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2158 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002159 .build();
2160 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002161 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002162 InputEventInjectionSync::WAIT_FOR_RESULT));
2163 rightWindow->consumeMotionMove();
2164
2165 leftWindow->assertNoEvents();
2166 rightWindow->assertNoEvents();
2167 wallpaperWindow->assertNoEvents();
2168}
2169
Arthur Hungc539dbb2022-12-08 07:45:36 +00002170/**
2171 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2172 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2173 * The right window should receive ACTION_DOWN.
2174 */
2175TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002176 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002177 sp<FakeWindowHandle> leftWindow =
2178 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2179 leftWindow->setFrame(Rect(0, 0, 200, 200));
2180 leftWindow->setDupTouchToWallpaper(true);
2181 leftWindow->setSlippery(true);
2182
2183 sp<FakeWindowHandle> rightWindow =
2184 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2185 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002186
2187 sp<FakeWindowHandle> wallpaperWindow =
2188 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2189 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002190
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002191 mDispatcher->onWindowInfosChanged(
2192 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2193 {},
2194 0,
2195 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002196
Arthur Hungc539dbb2022-12-08 07:45:36 +00002197 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002198 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002199 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002200 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002201 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002202
2203 // Both foreground window and its wallpaper should receive the touch down
2204 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002205 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2206
Arthur Hungc539dbb2022-12-08 07:45:36 +00002207 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002208 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002209 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002210 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002211 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2212
Arthur Hungc539dbb2022-12-08 07:45:36 +00002213 leftWindow->consumeMotionCancel();
2214 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2215 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002216}
2217
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002218/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002219 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2220 * interactive, it might stop sending this flag.
2221 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2222 * to have a consistent input stream.
2223 *
2224 * Test procedure:
2225 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2226 * DOWN (new gesture).
2227 *
2228 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2229 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2230 *
2231 * We technically just need a single window here, but we are using two windows (spy on top and a
2232 * regular window below) to emulate the actual situation where it happens on the device.
2233 */
2234TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2235 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2236 sp<FakeWindowHandle> spyWindow =
2237 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2238 spyWindow->setFrame(Rect(0, 0, 200, 200));
2239 spyWindow->setTrustedOverlay(true);
2240 spyWindow->setSpy(true);
2241
2242 sp<FakeWindowHandle> window =
2243 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2244 window->setFrame(Rect(0, 0, 200, 200));
2245
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002246 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002247 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002248
2249 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002250 mDispatcher->notifyMotion(
2251 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2252 .deviceId(touchDeviceId)
2253 .policyFlags(DEFAULT_POLICY_FLAGS)
2254 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2255 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002256
Prabir Pradhan678438e2023-04-13 19:32:51 +00002257 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2258 .deviceId(touchDeviceId)
2259 .policyFlags(DEFAULT_POLICY_FLAGS)
2260 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2261 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2262 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002263 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2264 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2265 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2266 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2267
2268 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002269 mDispatcher->notifyMotion(
2270 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2271 .deviceId(touchDeviceId)
2272 .policyFlags(0)
2273 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2274 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2275 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002276 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2277 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2278
2279 // We don't need to reset the device to reproduce the issue, but the reset event typically
2280 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002281 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002282
2283 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002284 mDispatcher->notifyMotion(
2285 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2286 .deviceId(touchDeviceId)
2287 .policyFlags(DEFAULT_POLICY_FLAGS)
2288 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2289 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002290 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2291 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2292
2293 // No more events
2294 spyWindow->assertNoEvents();
2295 window->assertNoEvents();
2296}
2297
2298/**
Linnan Li907ae732023-09-05 17:14:21 +08002299 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
2300 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2301 * interactive, it might stop sending this flag.
2302 * We've already ensured the consistency of the touch event in this case, and we should also ensure
2303 * the consistency of the hover event in this case.
2304 *
2305 * Test procedure:
2306 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
2307 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
2308 *
2309 * We expect to receive two full streams of hover events.
2310 */
2311TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
2312 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2313
2314 sp<FakeWindowHandle> window =
2315 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2316 window->setFrame(Rect(0, 0, 300, 300));
2317
2318 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2319
2320 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2321 .policyFlags(DEFAULT_POLICY_FLAGS)
2322 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2323 .build());
2324 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2325
2326 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2327 .policyFlags(DEFAULT_POLICY_FLAGS)
2328 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2329 .build());
2330 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2331
2332 // Send hover exit without the default policy flags.
2333 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2334 .policyFlags(0)
2335 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2336 .build());
2337
2338 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2339
2340 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
2341 // right event.
2342 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2343 .policyFlags(DEFAULT_POLICY_FLAGS)
2344 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
2345 .build());
2346 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2347
2348 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2349 .policyFlags(DEFAULT_POLICY_FLAGS)
2350 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2351 .build());
2352 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2353
2354 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2355 .policyFlags(DEFAULT_POLICY_FLAGS)
2356 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2357 .build());
2358 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2359}
2360
2361/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002362 * Two windows: a window on the left and a window on the right.
2363 * Mouse is hovered from the right window into the left window.
2364 * Next, we tap on the left window, where the cursor was last seen.
2365 * The second tap is done onto the right window.
2366 * The mouse and tap are from two different devices.
2367 * We technically don't need to set the downtime / eventtime for these events, but setting these
2368 * explicitly helps during debugging.
2369 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2370 * In the buggy implementation, a tap on the right window would cause a crash.
2371 */
2372TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2373 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2374 sp<FakeWindowHandle> leftWindow =
2375 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2376 leftWindow->setFrame(Rect(0, 0, 200, 200));
2377
2378 sp<FakeWindowHandle> rightWindow =
2379 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2380 rightWindow->setFrame(Rect(200, 0, 400, 200));
2381
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002382 mDispatcher->onWindowInfosChanged(
2383 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002384 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2385 // stale.
2386 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2387 const int32_t mouseDeviceId = 6;
2388 const int32_t touchDeviceId = 4;
2389 // Move the cursor from right
2390 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002391 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002392 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2393 AINPUT_SOURCE_MOUSE)
2394 .deviceId(mouseDeviceId)
2395 .downTime(baseTime + 10)
2396 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002397 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002398 .build()));
2399 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2400
2401 // .. to the left window
2402 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002403 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002404 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2405 AINPUT_SOURCE_MOUSE)
2406 .deviceId(mouseDeviceId)
2407 .downTime(baseTime + 10)
2408 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002409 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002410 .build()));
2411 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2412 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2413 // Now tap the left window
2414 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002415 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002416 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2417 AINPUT_SOURCE_TOUCHSCREEN)
2418 .deviceId(touchDeviceId)
2419 .downTime(baseTime + 40)
2420 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002421 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002422 .build()));
2423 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2424 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2425
2426 // release tap
2427 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002428 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002429 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2430 AINPUT_SOURCE_TOUCHSCREEN)
2431 .deviceId(touchDeviceId)
2432 .downTime(baseTime + 40)
2433 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002434 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002435 .build()));
2436 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2437
2438 // Tap the window on the right
2439 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002440 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002441 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2442 AINPUT_SOURCE_TOUCHSCREEN)
2443 .deviceId(touchDeviceId)
2444 .downTime(baseTime + 60)
2445 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002446 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002447 .build()));
2448 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2449
2450 // release tap
2451 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002452 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002453 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2454 AINPUT_SOURCE_TOUCHSCREEN)
2455 .deviceId(touchDeviceId)
2456 .downTime(baseTime + 60)
2457 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002458 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002459 .build()));
2460 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2461
2462 // No more events
2463 leftWindow->assertNoEvents();
2464 rightWindow->assertNoEvents();
2465}
2466
2467/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002468 * Start hovering in a window. While this hover is still active, make another window appear on top.
2469 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2470 * While the top window is present, the hovering is stopped.
2471 * Later, hovering gets resumed again.
2472 * Ensure that new hover gesture is handled correctly.
2473 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2474 * to the window that's currently being hovered over.
2475 */
2476TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2477 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2478 sp<FakeWindowHandle> window =
2479 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2480 window->setFrame(Rect(0, 0, 200, 200));
2481
2482 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002483 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002484
2485 // Start hovering in the window
2486 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2487 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2488 .build());
2489 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2490
2491 // Now, an obscuring window appears!
2492 sp<FakeWindowHandle> obscuringWindow =
2493 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2494 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002495 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002496 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2497 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2498 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2499 obscuringWindow->setNoInputChannel(true);
2500 obscuringWindow->setFocusable(false);
2501 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002502 mDispatcher->onWindowInfosChanged(
2503 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002504
2505 // While this new obscuring window is present, the hovering is stopped
2506 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2507 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2508 .build());
2509 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2510
2511 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002512 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002513
2514 // And a new hover gesture starts.
2515 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2516 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2517 .build());
2518 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2519}
2520
2521/**
2522 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2523 * the obscuring window.
2524 */
2525TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2526 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2527 sp<FakeWindowHandle> window =
2528 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2529 window->setFrame(Rect(0, 0, 200, 200));
2530
2531 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002532 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002533
2534 // Start hovering in the window
2535 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2536 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2537 .build());
2538 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2539
2540 // Now, an obscuring window appears!
2541 sp<FakeWindowHandle> obscuringWindow =
2542 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2543 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002544 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002545 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2546 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2547 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2548 obscuringWindow->setNoInputChannel(true);
2549 obscuringWindow->setFocusable(false);
2550 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002551 mDispatcher->onWindowInfosChanged(
2552 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002553
2554 // While this new obscuring window is present, the hovering continues. The event can't go to the
2555 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2556 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2557 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2558 .build());
2559 obscuringWindow->assertNoEvents();
2560 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2561
2562 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002563 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002564
2565 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2566 // so it should generate a HOVER_ENTER
2567 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2568 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2569 .build());
2570 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2571
2572 // Now the MOVE should be getting dispatched normally
2573 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2574 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2575 .build());
2576 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2577}
2578
2579/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002580 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2581 * events are delivered to the window.
2582 */
2583TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2584 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2585 sp<FakeWindowHandle> window =
2586 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2587 window->setFrame(Rect(0, 0, 200, 200));
2588 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2589
2590 // Start hovering in the window
2591 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2592 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2593 .build());
2594 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2595
2596 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2597 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2598 .build());
2599 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2600
2601 // Scroll with the mouse
2602 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2603 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2604 .build());
2605 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2606}
2607
2608using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2609
2610/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002611 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2612 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002613 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002614TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002615 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2616 sp<FakeWindowHandle> window =
2617 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2618 window->setFrame(Rect(0, 0, 200, 200));
2619
2620 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2621
2622 constexpr int32_t touchDeviceId = 4;
2623 constexpr int32_t stylusDeviceId = 2;
2624
2625 // Stylus down
2626 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2627 .deviceId(stylusDeviceId)
2628 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2629 .build());
2630 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2631
2632 // Touch down
2633 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2634 .deviceId(touchDeviceId)
2635 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2636 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002637
2638 // Touch move
2639 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2640 .deviceId(touchDeviceId)
2641 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2642 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002643 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002644
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002645 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002646 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2647 .deviceId(stylusDeviceId)
2648 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2649 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002650 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2651 WithCoords(101, 111)));
2652
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002653 window->assertNoEvents();
2654}
2655
2656/**
2657 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002658 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002659 * Similar test as above, but with added SPY window.
2660 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002661TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002662 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2663 sp<FakeWindowHandle> window =
2664 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2665 sp<FakeWindowHandle> spyWindow =
2666 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2667 spyWindow->setFrame(Rect(0, 0, 200, 200));
2668 spyWindow->setTrustedOverlay(true);
2669 spyWindow->setSpy(true);
2670 window->setFrame(Rect(0, 0, 200, 200));
2671
2672 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2673
2674 constexpr int32_t touchDeviceId = 4;
2675 constexpr int32_t stylusDeviceId = 2;
2676
2677 // Stylus down
2678 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2679 .deviceId(stylusDeviceId)
2680 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2681 .build());
2682 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2683 spyWindow->consumeMotionEvent(
2684 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2685
2686 // Touch down
2687 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2688 .deviceId(touchDeviceId)
2689 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2690 .build());
2691
2692 // Touch move
2693 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2694 .deviceId(touchDeviceId)
2695 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2696 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002697
2698 // Touch is ignored because stylus is already down
2699
2700 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002701 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2702 .deviceId(stylusDeviceId)
2703 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2704 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002705 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2706 WithCoords(101, 111)));
2707 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2708 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002709
2710 window->assertNoEvents();
2711 spyWindow->assertNoEvents();
2712}
2713
2714/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002715 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002716 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002717 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002718TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002719 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2720 sp<FakeWindowHandle> window =
2721 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2722 window->setFrame(Rect(0, 0, 200, 200));
2723
2724 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2725
2726 constexpr int32_t touchDeviceId = 4;
2727 constexpr int32_t stylusDeviceId = 2;
2728
2729 // Stylus down on the window
2730 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2731 .deviceId(stylusDeviceId)
2732 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2733 .build());
2734 window->consumeMotionEvent(
2735 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2736
2737 // Touch down on window
2738 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2739 .deviceId(touchDeviceId)
2740 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2741 .build());
2742 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2743 .deviceId(touchDeviceId)
2744 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2745 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002746
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002747 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002748
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002749 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002750 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2751 .deviceId(stylusDeviceId)
2752 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2753 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002754 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2755 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002756
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002757 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002758 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2759 .deviceId(touchDeviceId)
2760 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2761 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002762 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002763}
2764
2765/**
2766 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002767 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002768 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002769TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002770 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2771 sp<FakeWindowHandle> window =
2772 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2773 window->setFrame(Rect(0, 0, 200, 200));
2774
2775 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2776
2777 constexpr int32_t touchDeviceId = 4;
2778 constexpr int32_t stylusDeviceId = 2;
2779
2780 // Touch down on window
2781 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2782 .deviceId(touchDeviceId)
2783 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2784 .build());
2785 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2786 .deviceId(touchDeviceId)
2787 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2788 .build());
2789 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2790 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2791
2792 // Stylus hover on the window
2793 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2794 .deviceId(stylusDeviceId)
2795 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2796 .build());
2797 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2798 .deviceId(stylusDeviceId)
2799 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2800 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002801 // Stylus hover movement causes touch to be canceled
2802 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2803 WithCoords(141, 146)));
2804 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2805 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2806 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2807 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002808
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002809 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002810 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2811 .deviceId(touchDeviceId)
2812 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2813 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002814
2815 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002816}
2817
2818/**
2819 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2820 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2821 * become active.
2822 */
2823TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
2824 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2825 sp<FakeWindowHandle> window =
2826 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2827 window->setFrame(Rect(0, 0, 200, 200));
2828
2829 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2830
2831 constexpr int32_t stylusDeviceId1 = 3;
2832 constexpr int32_t stylusDeviceId2 = 5;
2833
2834 // Touch down on window
2835 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2836 .deviceId(stylusDeviceId1)
2837 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2838 .build());
2839 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2840 .deviceId(stylusDeviceId1)
2841 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2842 .build());
2843 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2844 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2845
2846 // Second stylus down
2847 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2848 .deviceId(stylusDeviceId2)
2849 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2850 .build());
2851 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2852 .deviceId(stylusDeviceId2)
2853 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2854 .build());
2855
2856 // First stylus is canceled, second one takes over.
2857 window->consumeMotionEvent(
2858 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2859 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2860 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2861
2862 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2863 .deviceId(stylusDeviceId1)
2864 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2865 .build());
2866 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002867 window->assertNoEvents();
2868}
2869
2870/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002871 * One window. Touch down on the window. Then, stylus down on the window from another device.
2872 * Ensure that is canceled, because stylus down should be preferred over touch.
2873 */
2874TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
2875 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2876 sp<FakeWindowHandle> window =
2877 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2878 window->setFrame(Rect(0, 0, 200, 200));
2879
2880 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2881
2882 constexpr int32_t touchDeviceId = 4;
2883 constexpr int32_t stylusDeviceId = 2;
2884
2885 // Touch down on window
2886 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2887 .deviceId(touchDeviceId)
2888 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2889 .build());
2890 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2891 .deviceId(touchDeviceId)
2892 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2893 .build());
2894 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2895 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2896
2897 // Stylus down on the window
2898 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2899 .deviceId(stylusDeviceId)
2900 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2901 .build());
2902 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2903 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2904
2905 // Subsequent stylus movements are delivered correctly
2906 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2907 .deviceId(stylusDeviceId)
2908 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2909 .build());
2910 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2911 WithCoords(101, 111)));
2912}
2913
2914/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002915 * Two windows: a window on the left and a window on the right.
2916 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2917 * down. Then, on the left window, also place second touch pointer down.
2918 * This test tries to reproduce a crash.
2919 * In the buggy implementation, second pointer down on the left window would cause a crash.
2920 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002921TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002922 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2923 sp<FakeWindowHandle> leftWindow =
2924 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2925 leftWindow->setFrame(Rect(0, 0, 200, 200));
2926
2927 sp<FakeWindowHandle> rightWindow =
2928 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2929 rightWindow->setFrame(Rect(200, 0, 400, 200));
2930
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002931 mDispatcher->onWindowInfosChanged(
2932 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002933
2934 const int32_t touchDeviceId = 4;
2935 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002936
2937 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002938 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2939 .deviceId(mouseDeviceId)
2940 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2941 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002942 leftWindow->consumeMotionEvent(
2943 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2944
2945 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002946 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2947 .deviceId(mouseDeviceId)
2948 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2949 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2950 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002951
2952 leftWindow->consumeMotionEvent(
2953 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2954 leftWindow->consumeMotionEvent(
2955 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2956
Prabir Pradhan678438e2023-04-13 19:32:51 +00002957 mDispatcher->notifyMotion(
2958 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2959 .deviceId(mouseDeviceId)
2960 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2961 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2962 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2963 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002964 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2965
2966 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002967 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2968 .deviceId(touchDeviceId)
2969 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2970 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002971 leftWindow->assertNoEvents();
2972
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002973 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2974
2975 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002976 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2977 .deviceId(touchDeviceId)
2978 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2979 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2980 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002981 // Since this is now a new splittable pointer going down on the left window, and it's coming
2982 // from a different device, the current gesture in the left window (pointer down) should first
2983 // be canceled.
2984 leftWindow->consumeMotionEvent(
2985 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002986 leftWindow->consumeMotionEvent(
2987 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2988 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2989 // current implementation.
2990 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2991 rightWindow->consumeMotionEvent(
2992 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2993
2994 leftWindow->assertNoEvents();
2995 rightWindow->assertNoEvents();
2996}
2997
2998/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002999 * Two windows: a window on the left and a window on the right.
3000 * Mouse is hovered on the left window and stylus is hovered on the right window.
3001 */
3002TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
3003 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3004 sp<FakeWindowHandle> leftWindow =
3005 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3006 leftWindow->setFrame(Rect(0, 0, 200, 200));
3007
3008 sp<FakeWindowHandle> rightWindow =
3009 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3010 rightWindow->setFrame(Rect(200, 0, 400, 200));
3011
3012 mDispatcher->onWindowInfosChanged(
3013 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3014
3015 const int32_t stylusDeviceId = 3;
3016 const int32_t mouseDeviceId = 6;
3017
3018 // Start hovering over the left window
3019 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3020 .deviceId(mouseDeviceId)
3021 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
3022 .build());
3023 leftWindow->consumeMotionEvent(
3024 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3025
3026 // Stylus hovered on right window
3027 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3028 .deviceId(stylusDeviceId)
3029 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
3030 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003031 rightWindow->consumeMotionEvent(
3032 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3033
3034 // Subsequent HOVER_MOVE events are dispatched correctly.
3035 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
3036 .deviceId(mouseDeviceId)
3037 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
3038 .build());
3039 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003040 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003041
3042 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3043 .deviceId(stylusDeviceId)
3044 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
3045 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003046 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003047 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003048
3049 leftWindow->assertNoEvents();
3050 rightWindow->assertNoEvents();
3051}
3052
3053/**
3054 * Three windows: a window on the left and a window on the right.
3055 * And a spy window that's positioned above all of them.
3056 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
3057 * Check the stream that's received by the spy.
3058 */
3059TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
3060 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3061
3062 sp<FakeWindowHandle> spyWindow =
3063 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3064 spyWindow->setFrame(Rect(0, 0, 400, 400));
3065 spyWindow->setTrustedOverlay(true);
3066 spyWindow->setSpy(true);
3067
3068 sp<FakeWindowHandle> leftWindow =
3069 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3070 leftWindow->setFrame(Rect(0, 0, 200, 200));
3071
3072 sp<FakeWindowHandle> rightWindow =
3073 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3074
3075 rightWindow->setFrame(Rect(200, 0, 400, 200));
3076
3077 mDispatcher->onWindowInfosChanged(
3078 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3079
3080 const int32_t stylusDeviceId = 1;
3081 const int32_t touchDeviceId = 2;
3082
3083 // Stylus down on the left window
3084 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3085 .deviceId(stylusDeviceId)
3086 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3087 .build());
3088 leftWindow->consumeMotionEvent(
3089 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3090 spyWindow->consumeMotionEvent(
3091 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3092
3093 // Touch down on the right window
3094 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3095 .deviceId(touchDeviceId)
3096 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3097 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003098 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003099 rightWindow->consumeMotionEvent(
3100 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003101
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003102 // Spy window does not receive touch events, because stylus events take precedence, and it
3103 // already has an active stylus gesture.
3104
3105 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003106 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3107 .deviceId(stylusDeviceId)
3108 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3109 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003110 leftWindow->consumeMotionEvent(
3111 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3112 spyWindow->consumeMotionEvent(
3113 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003114
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003115 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003116 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3117 .deviceId(touchDeviceId)
3118 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
3119 .build());
3120 rightWindow->consumeMotionEvent(
3121 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003122
3123 spyWindow->assertNoEvents();
3124 leftWindow->assertNoEvents();
3125 rightWindow->assertNoEvents();
3126}
3127
3128/**
3129 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3130 * both.
3131 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003132 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003133 * At the same time, left and right should be getting independent streams of hovering and touch,
3134 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003135 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003136TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003137 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3138
3139 sp<FakeWindowHandle> spyWindow =
3140 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3141 spyWindow->setFrame(Rect(0, 0, 400, 400));
3142 spyWindow->setTrustedOverlay(true);
3143 spyWindow->setSpy(true);
3144
3145 sp<FakeWindowHandle> leftWindow =
3146 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3147 leftWindow->setFrame(Rect(0, 0, 200, 200));
3148
3149 sp<FakeWindowHandle> rightWindow =
3150 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3151 rightWindow->setFrame(Rect(200, 0, 400, 200));
3152
3153 mDispatcher->onWindowInfosChanged(
3154 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3155
3156 const int32_t stylusDeviceId = 1;
3157 const int32_t touchDeviceId = 2;
3158
3159 // Stylus hover on the left window
3160 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3161 .deviceId(stylusDeviceId)
3162 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3163 .build());
3164 leftWindow->consumeMotionEvent(
3165 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3166 spyWindow->consumeMotionEvent(
3167 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3168
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003169 // Touch down on the right window. Spy doesn't receive this touch because it already has
3170 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003171 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3172 .deviceId(touchDeviceId)
3173 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3174 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003175 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003176 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003177 rightWindow->consumeMotionEvent(
3178 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3179
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003180 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003181 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3182 .deviceId(stylusDeviceId)
3183 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3184 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003185 leftWindow->consumeMotionEvent(
3186 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003187 spyWindow->consumeMotionEvent(
3188 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003189
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003190 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003191 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3192 .deviceId(touchDeviceId)
3193 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3194 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003195 rightWindow->consumeMotionEvent(
3196 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3197
3198 spyWindow->assertNoEvents();
3199 leftWindow->assertNoEvents();
3200 rightWindow->assertNoEvents();
3201}
3202
3203/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003204 * On a single window, use two different devices: mouse and touch.
3205 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3206 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3207 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3208 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3209 * represent a new gesture.
3210 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003211TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003212 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3213 sp<FakeWindowHandle> window =
3214 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3215 window->setFrame(Rect(0, 0, 400, 400));
3216
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003217 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003218
3219 const int32_t touchDeviceId = 4;
3220 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003221
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003222 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003223 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3224 .deviceId(touchDeviceId)
3225 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3226 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003227 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003228 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3229 .deviceId(touchDeviceId)
3230 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3231 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3232 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003233 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003234 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3235 .deviceId(touchDeviceId)
3236 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3237 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3238 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003239 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3240 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3241 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3242
3243 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003244 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3245 .deviceId(mouseDeviceId)
3246 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3247 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3248 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003249
3250 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003251 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003252 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3253
Prabir Pradhan678438e2023-04-13 19:32:51 +00003254 mDispatcher->notifyMotion(
3255 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3256 .deviceId(mouseDeviceId)
3257 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3258 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3259 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3260 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003261 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3262
3263 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003264 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3265 .deviceId(touchDeviceId)
3266 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3267 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3268 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003269 // Since we already canceled this touch gesture, it will be ignored until a completely new
3270 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3271 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3272 // However, mouse movements should continue to work.
3273 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3274 .deviceId(mouseDeviceId)
3275 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3276 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3277 .build());
3278 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3279
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003280 window->assertNoEvents();
3281}
3282
3283/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003284 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3285 * the injected event.
3286 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003287TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003288 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3289 sp<FakeWindowHandle> window =
3290 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3291 window->setFrame(Rect(0, 0, 400, 400));
3292
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003293 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003294
3295 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003296 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3297 // completion.
3298 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003299 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003300 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3301 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003302 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003303 .build()));
3304 window->consumeMotionEvent(
3305 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3306
3307 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3308 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003309 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3310 .deviceId(touchDeviceId)
3311 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3312 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003313
3314 window->consumeMotionEvent(
3315 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3316 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3317}
3318
3319/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003320 * This test is similar to the test above, but the sequence of injected events is different.
3321 *
3322 * Two windows: a window on the left and a window on the right.
3323 * Mouse is hovered over the left window.
3324 * Next, we tap on the left window, where the cursor was last seen.
3325 *
3326 * After that, we inject one finger down onto the right window, and then a second finger down onto
3327 * the left window.
3328 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3329 * window (first), and then another on the left window (second).
3330 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3331 * In the buggy implementation, second finger down on the left window would cause a crash.
3332 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003333TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003334 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3335 sp<FakeWindowHandle> leftWindow =
3336 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3337 leftWindow->setFrame(Rect(0, 0, 200, 200));
3338
3339 sp<FakeWindowHandle> rightWindow =
3340 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3341 rightWindow->setFrame(Rect(200, 0, 400, 200));
3342
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003343 mDispatcher->onWindowInfosChanged(
3344 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003345
3346 const int32_t mouseDeviceId = 6;
3347 const int32_t touchDeviceId = 4;
3348 // Hover over the left window. Keep the cursor there.
3349 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003350 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003351 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3352 AINPUT_SOURCE_MOUSE)
3353 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003354 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003355 .build()));
3356 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3357
3358 // Tap on left window
3359 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003360 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003361 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3362 AINPUT_SOURCE_TOUCHSCREEN)
3363 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003364 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003365 .build()));
3366
3367 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003368 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003369 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3370 AINPUT_SOURCE_TOUCHSCREEN)
3371 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003372 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003373 .build()));
3374 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3375 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3376 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3377
3378 // First finger down on right window
3379 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003380 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003381 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3382 AINPUT_SOURCE_TOUCHSCREEN)
3383 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003384 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003385 .build()));
3386 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3387
3388 // Second finger down on the left window
3389 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003390 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003391 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3392 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003393 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3394 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003395 .build()));
3396 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3397 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3398
3399 // No more events
3400 leftWindow->assertNoEvents();
3401 rightWindow->assertNoEvents();
3402}
3403
3404/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003405 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3406 * While the touch is down, new hover events from the stylus device should be ignored. After the
3407 * touch is gone, stylus hovering should start working again.
3408 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003409TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003410 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3411 sp<FakeWindowHandle> window =
3412 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3413 window->setFrame(Rect(0, 0, 200, 200));
3414
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003415 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003416
3417 const int32_t stylusDeviceId = 5;
3418 const int32_t touchDeviceId = 4;
3419 // Start hovering with stylus
3420 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003421 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003422 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003423 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003424 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003425 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003426 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003427
3428 // Finger down on the window
3429 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003430 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003431 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003432 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003433 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003434 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003435 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003436
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003437 // Continue hovering with stylus.
3438 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003439 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003440 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3441 AINPUT_SOURCE_STYLUS)
3442 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003443 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003444 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003445 // Hovers continue to work
3446 window->consumeMotionEvent(
3447 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003448
3449 // Lift up the finger
3450 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003451 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003452 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3453 AINPUT_SOURCE_TOUCHSCREEN)
3454 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003455 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003456 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003457
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003458 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003459 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003460 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3461 AINPUT_SOURCE_STYLUS)
3462 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003463 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003464 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003465 window->consumeMotionEvent(
3466 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003467 window->assertNoEvents();
3468}
3469
3470/**
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003471 * If stylus is down anywhere on the screen, then touches should not be delivered to windows that
3472 * have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3473 *
3474 * Two windows: one on the left and one on the right.
3475 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3476 * Stylus down on the left window, and then touch down on the right window.
3477 * Check that the right window doesn't get touches while the stylus is down on the left window.
3478 */
3479TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusDownBlocksTouch) {
3480 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3481 sp<FakeWindowHandle> leftWindow =
3482 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3483 ADISPLAY_ID_DEFAULT);
3484 leftWindow->setFrame(Rect(0, 0, 100, 100));
3485
3486 sp<FakeWindowHandle> sbtRightWindow =
3487 sp<FakeWindowHandle>::make(application, mDispatcher,
3488 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3489 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3490 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3491
3492 mDispatcher->onWindowInfosChanged(
3493 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3494
3495 const int32_t stylusDeviceId = 5;
3496 const int32_t touchDeviceId = 4;
3497
3498 // Stylus down in the left window
3499 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3500 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3501 .deviceId(stylusDeviceId)
3502 .build());
3503 leftWindow->consumeMotionEvent(
3504 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3505
3506 // Finger tap on the right window
3507 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3508 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3509 .deviceId(touchDeviceId)
3510 .build());
3511 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3512 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3513 .deviceId(touchDeviceId)
3514 .build());
3515
3516 // The touch should be blocked, because stylus is down somewhere else on screen!
3517 sbtRightWindow->assertNoEvents();
3518
3519 // Continue stylus motion, and ensure it's not impacted.
3520 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3521 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3522 .deviceId(stylusDeviceId)
3523 .build());
3524 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3525 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3526 .deviceId(stylusDeviceId)
3527 .build());
3528 leftWindow->consumeMotionEvent(
3529 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3530 leftWindow->consumeMotionEvent(
3531 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(stylusDeviceId)));
3532
3533 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3534 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3535 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3536 .deviceId(touchDeviceId)
3537 .build());
3538 sbtRightWindow->consumeMotionEvent(
3539 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3540}
3541
3542/**
3543 * If stylus is hovering anywhere on the screen, then touches should not be delivered to windows
3544 * that have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3545 *
3546 * Two windows: one on the left and one on the right.
3547 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3548 * Stylus hover on the left window, and then touch down on the right window.
3549 * Check that the right window doesn't get touches while the stylus is hovering on the left window.
3550 */
3551TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusHoverBlocksTouch) {
3552 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3553 sp<FakeWindowHandle> leftWindow =
3554 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3555 ADISPLAY_ID_DEFAULT);
3556 leftWindow->setFrame(Rect(0, 0, 100, 100));
3557
3558 sp<FakeWindowHandle> sbtRightWindow =
3559 sp<FakeWindowHandle>::make(application, mDispatcher,
3560 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3561 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3562 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3563
3564 mDispatcher->onWindowInfosChanged(
3565 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3566
3567 const int32_t stylusDeviceId = 5;
3568 const int32_t touchDeviceId = 4;
3569
3570 // Stylus hover in the left window
3571 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3572 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3573 .deviceId(stylusDeviceId)
3574 .build());
3575 leftWindow->consumeMotionEvent(
3576 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3577
3578 // Finger tap on the right window
3579 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3580 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3581 .deviceId(touchDeviceId)
3582 .build());
3583 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3584 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3585 .deviceId(touchDeviceId)
3586 .build());
3587
3588 // The touch should be blocked, because stylus is hovering somewhere else on screen!
3589 sbtRightWindow->assertNoEvents();
3590
3591 // Continue stylus motion, and ensure it's not impacted.
3592 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3593 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3594 .deviceId(stylusDeviceId)
3595 .build());
3596 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3597 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3598 .deviceId(stylusDeviceId)
3599 .build());
3600 leftWindow->consumeMotionEvent(
3601 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3602 leftWindow->consumeMotionEvent(
3603 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3604
3605 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3606 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3607 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3608 .deviceId(touchDeviceId)
3609 .build());
3610 sbtRightWindow->consumeMotionEvent(
3611 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3612}
3613
3614/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003615 * A spy window above a window with no input channel.
3616 * Start hovering with a stylus device, and then tap with it.
3617 * Ensure spy window receives the entire sequence.
3618 */
3619TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3620 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3621 sp<FakeWindowHandle> spyWindow =
3622 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3623 spyWindow->setFrame(Rect(0, 0, 200, 200));
3624 spyWindow->setTrustedOverlay(true);
3625 spyWindow->setSpy(true);
3626 sp<FakeWindowHandle> window =
3627 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3628 window->setNoInputChannel(true);
3629 window->setFrame(Rect(0, 0, 200, 200));
3630
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003631 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003632
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003633 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003634 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3635 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3636 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003637 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3638 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003639 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3640 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3641 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003642 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3643
3644 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003645 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3646 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3647 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003648 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3649
3650 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003651 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3652 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3653 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003654 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3655
3656 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003657 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3658 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3659 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003660 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3661 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003662 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3663 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3664 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003665 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3666
3667 // No more events
3668 spyWindow->assertNoEvents();
3669 window->assertNoEvents();
3670}
3671
3672/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003673 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3674 * rejected. But since we already have an ongoing gesture, this event should be processed.
3675 * This prevents inconsistent events being handled inside the dispatcher.
3676 */
3677TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3678 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3679
3680 sp<FakeWindowHandle> window =
3681 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3682 window->setFrame(Rect(0, 0, 200, 200));
3683
3684 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3685
3686 // Start hovering with stylus
3687 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3688 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3689 .build());
3690 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3691
3692 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3693 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3694 .build();
3695 // Make this 'hoverExit' event stale
3696 mFakePolicy->setStaleEventTimeout(100ms);
3697 std::this_thread::sleep_for(100ms);
3698
3699 // It shouldn't be dropped by the dispatcher, even though it's stale.
3700 mDispatcher->notifyMotion(hoverExit);
3701 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3702
3703 // Stylus starts hovering again! There should be no crash.
3704 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3705 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3706 .build());
3707 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3708}
3709
3710/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003711 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3712 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3713 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3714 * While the mouse is down, new move events from the touch device should be ignored.
3715 */
3716TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3717 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3718 sp<FakeWindowHandle> spyWindow =
3719 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3720 spyWindow->setFrame(Rect(0, 0, 200, 200));
3721 spyWindow->setTrustedOverlay(true);
3722 spyWindow->setSpy(true);
3723 sp<FakeWindowHandle> window =
3724 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3725 window->setFrame(Rect(0, 0, 200, 200));
3726
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003727 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003728
3729 const int32_t mouseDeviceId = 7;
3730 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003731
3732 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003733 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3734 .deviceId(mouseDeviceId)
3735 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3736 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003737 spyWindow->consumeMotionEvent(
3738 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3739 window->consumeMotionEvent(
3740 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3741
3742 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003743 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3744 .deviceId(touchDeviceId)
3745 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3746 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003747 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3748 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3749 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3750 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3751
Prabir Pradhan678438e2023-04-13 19:32:51 +00003752 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3753 .deviceId(touchDeviceId)
3754 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3755 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003756 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3757 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3758
3759 // Pilfer the stream
3760 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3761 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3762
Prabir Pradhan678438e2023-04-13 19:32:51 +00003763 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3764 .deviceId(touchDeviceId)
3765 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3766 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003767 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3768
3769 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003770 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3771 .deviceId(mouseDeviceId)
3772 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3773 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3774 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003775
3776 spyWindow->consumeMotionEvent(
3777 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3778 spyWindow->consumeMotionEvent(
3779 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3780 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3781
Prabir Pradhan678438e2023-04-13 19:32:51 +00003782 mDispatcher->notifyMotion(
3783 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3784 .deviceId(mouseDeviceId)
3785 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3786 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3787 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3788 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003789 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3790 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3791
3792 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003793 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3794 .deviceId(mouseDeviceId)
3795 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3796 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3797 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003798 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3799 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3800
3801 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003802 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3803 .deviceId(touchDeviceId)
3804 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3805 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003806
3807 // No more events
3808 spyWindow->assertNoEvents();
3809 window->assertNoEvents();
3810}
3811
3812/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003813 * On the display, have a single window, and also an area where there's no window.
3814 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3815 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3816 */
3817TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3818 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3819 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003820 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003821
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003822 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003823
3824 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003825 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003826
3827 mDispatcher->waitForIdle();
3828 window->assertNoEvents();
3829
3830 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003831 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003832 mDispatcher->waitForIdle();
3833 window->consumeMotionDown();
3834}
3835
3836/**
3837 * Same test as above, but instead of touching the empty space, the first touch goes to
3838 * non-touchable window.
3839 */
3840TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3841 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3842 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003843 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003844 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3845 window1->setTouchable(false);
3846 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003847 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003848 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3849
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003850 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003851
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003852 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003853 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003854
3855 mDispatcher->waitForIdle();
3856 window1->assertNoEvents();
3857 window2->assertNoEvents();
3858
3859 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003860 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003861 mDispatcher->waitForIdle();
3862 window2->consumeMotionDown();
3863}
3864
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003865/**
3866 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3867 * to the event time of the first ACTION_DOWN sent to the particular window.
3868 */
3869TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3870 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3871 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003872 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003873 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3874 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003875 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003876 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3877
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003878 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003879
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003880 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003881 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003882 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003883
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003884 const std::unique_ptr<MotionEvent> firstDown =
3885 window1->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
3886 ASSERT_EQ(firstDown->getDownTime(), firstDown->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003887 window2->assertNoEvents();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003888
3889 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003890 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003891 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003892
3893 const std::unique_ptr<MotionEvent> secondDown =
3894 window2->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
3895 ASSERT_EQ(secondDown->getDownTime(), secondDown->getEventTime());
3896 ASSERT_NE(firstDown->getDownTime(), secondDown->getDownTime());
3897 // We currently send MOVE events to all windows receiving a split touch when there is any change
3898 // in the touch state, even when none of the pointers in the split window actually moved.
3899 // Document this behavior in the test.
3900 window1->consumeMotionMove();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003901
3902 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003903 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003904 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003905
3906 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
3907 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003908
3909 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003910 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003911 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003912
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003913 window2->consumeMotionEvent(
3914 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(secondDown->getDownTime())));
3915 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003916
3917 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003918 mDispatcher->notifyMotion(
3919 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003920 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003921
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003922 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
3923 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
3924
3925 // Now add new touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003926 mDispatcher->notifyMotion(
3927 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003928 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003929
3930 window1->consumeMotionEvent(
3931 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(firstDown->getDownTime())));
3932 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003933}
3934
Garfield Tandf26e862020-07-01 20:18:19 -07003935TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003936 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003937 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003938 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003939 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003940 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003941 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003942 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003943
3944 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3945
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003946 mDispatcher->onWindowInfosChanged(
3947 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003948
3949 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003950 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003951 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003952 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3953 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003954 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003955 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003956 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003957
3958 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003959 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003960 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003961 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3962 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003963 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003964 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003965 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3966 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003967
3968 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003969 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003970 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003971 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3972 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003973 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003974 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003975 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3976 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003977
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003978 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003979 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003980 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3981 AINPUT_SOURCE_MOUSE)
3982 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3983 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003984 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003985 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003986 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003987
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003988 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003989 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003990 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3991 AINPUT_SOURCE_MOUSE)
3992 .buttonState(0)
3993 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003994 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003995 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003996 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003997
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003998 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003999 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004000 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4001 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004002 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004003 .build()));
4004 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
4005
4006 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004007 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004008 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004009 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4010 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004011 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004012 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004013 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004014
4015 // No more events
4016 windowLeft->assertNoEvents();
4017 windowRight->assertNoEvents();
4018}
4019
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004020/**
4021 * Put two fingers down (and don't release them) and click the mouse button.
4022 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
4023 * currently active gesture should be canceled, and the new one should proceed.
4024 */
4025TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
4026 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4027 sp<FakeWindowHandle> window =
4028 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4029 window->setFrame(Rect(0, 0, 600, 800));
4030
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004031 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004032
4033 const int32_t touchDeviceId = 4;
4034 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004035
4036 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004037 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4038 .deviceId(touchDeviceId)
4039 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4040 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004041
Prabir Pradhan678438e2023-04-13 19:32:51 +00004042 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4043 .deviceId(touchDeviceId)
4044 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4045 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4046 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004047 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4048 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4049
4050 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00004051 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4052 .deviceId(mouseDeviceId)
4053 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4054 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4055 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004056 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
4057 WithPointerCount(2u)));
4058 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4059
Prabir Pradhan678438e2023-04-13 19:32:51 +00004060 mDispatcher->notifyMotion(
4061 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4062 .deviceId(mouseDeviceId)
4063 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4064 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4065 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4066 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004067 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4068
4069 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4070 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004071 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4072 .deviceId(touchDeviceId)
4073 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4074 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4075 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004076 window->assertNoEvents();
4077}
4078
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004079TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
4080 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4081
4082 sp<FakeWindowHandle> spyWindow =
4083 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4084 spyWindow->setFrame(Rect(0, 0, 600, 800));
4085 spyWindow->setTrustedOverlay(true);
4086 spyWindow->setSpy(true);
4087 sp<FakeWindowHandle> window =
4088 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4089 window->setFrame(Rect(0, 0, 600, 800));
4090
4091 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004092 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004093
4094 // Send mouse cursor to the window
4095 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004096 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004097 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4098 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004099 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004100 .build()));
4101
4102 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4103 WithSource(AINPUT_SOURCE_MOUSE)));
4104 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4105 WithSource(AINPUT_SOURCE_MOUSE)));
4106
4107 window->assertNoEvents();
4108 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004109}
4110
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004111TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
4112 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4113
4114 sp<FakeWindowHandle> spyWindow =
4115 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4116 spyWindow->setFrame(Rect(0, 0, 600, 800));
4117 spyWindow->setTrustedOverlay(true);
4118 spyWindow->setSpy(true);
4119 sp<FakeWindowHandle> window =
4120 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4121 window->setFrame(Rect(0, 0, 600, 800));
4122
4123 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004124 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004125
4126 // Send mouse cursor to 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_HOVER_ENTER,
4130 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004131 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004132 .build()));
4133
4134 // Move mouse cursor
4135 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004136 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004137 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4138 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004139 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004140 .build()));
4141
4142 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4143 WithSource(AINPUT_SOURCE_MOUSE)));
4144 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4145 WithSource(AINPUT_SOURCE_MOUSE)));
4146 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4147 WithSource(AINPUT_SOURCE_MOUSE)));
4148 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4149 WithSource(AINPUT_SOURCE_MOUSE)));
4150 // Touch down on the window
4151 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004152 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004153 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4154 AINPUT_SOURCE_TOUCHSCREEN)
4155 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004156 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004157 .build()));
4158 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4159 WithSource(AINPUT_SOURCE_MOUSE)));
4160 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4161 WithSource(AINPUT_SOURCE_MOUSE)));
4162 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4163 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4164 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4165 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4166
4167 // pilfer the motion, retaining the gesture on the spy window.
4168 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4169 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4170 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4171
4172 // Touch UP on the window
4173 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004174 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004175 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4176 AINPUT_SOURCE_TOUCHSCREEN)
4177 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004178 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004179 .build()));
4180 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4181 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4182
4183 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4184 // to send a new gesture. It should again go to both windows (spy and the window below), just
4185 // like the first gesture did, before pilfering. The window configuration has not changed.
4186
4187 // One more tap - DOWN
4188 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004189 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004190 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4191 AINPUT_SOURCE_TOUCHSCREEN)
4192 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004193 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004194 .build()));
4195 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4196 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4197 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4198 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4199
4200 // Touch UP on the window
4201 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004202 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004203 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4204 AINPUT_SOURCE_TOUCHSCREEN)
4205 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004206 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004207 .build()));
4208 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4209 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4210 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4211 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4212
4213 window->assertNoEvents();
4214 spyWindow->assertNoEvents();
4215}
4216
Garfield Tandf26e862020-07-01 20:18:19 -07004217// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
4218// directly in this test.
4219TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004220 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07004221 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004222 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004223 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004224
4225 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4226
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004227 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004228
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004229 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004230 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004231 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4232 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004233 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004234 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004235 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004236 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004237 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004238 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004239 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4240 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004241 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004242 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004243 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4244 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004245
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004246 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004247 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004248 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4249 AINPUT_SOURCE_MOUSE)
4250 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4251 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004252 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004253 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004254 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004255
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004256 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004257 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004258 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4259 AINPUT_SOURCE_MOUSE)
4260 .buttonState(0)
4261 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004262 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004263 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004264 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004265
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004266 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004267 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004268 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4269 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004270 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004271 .build()));
4272 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
4273
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07004274 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
4275 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
4276 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004277 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004278 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
4279 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004280 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004281 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004282 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004283}
4284
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004285/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004286 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
4287 * is generated.
4288 */
4289TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
4290 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4291 sp<FakeWindowHandle> window =
4292 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4293 window->setFrame(Rect(0, 0, 1200, 800));
4294
4295 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4296
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004297 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004298
4299 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004300 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004301 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4302 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004303 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004304 .build()));
4305 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4306
4307 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004308 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004309 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4310}
4311
4312/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004313 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4314 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004315TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4316 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4317 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004318 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4319 sp<FakeWindowHandle> window =
4320 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4321 window->setFrame(Rect(0, 0, 1200, 800));
4322
4323 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4324
4325 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4326
4327 MotionEventBuilder hoverEnterBuilder =
4328 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4329 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4330 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4331 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4332 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4333 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4334 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4335 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4336 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4337}
4338
4339/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004340 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4341 */
4342TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4343 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4344 sp<FakeWindowHandle> window =
4345 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4346 window->setFrame(Rect(0, 0, 100, 100));
4347
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004348 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004349
4350 const int32_t mouseDeviceId = 7;
4351 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004352
4353 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004354 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4355 .deviceId(mouseDeviceId)
4356 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4357 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004358 window->consumeMotionEvent(
4359 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4360
4361 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004362 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4363 .deviceId(touchDeviceId)
4364 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4365 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004366
4367 window->consumeMotionEvent(
4368 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4369 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4370}
4371
4372/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004373 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004374 * The tap causes a HOVER_EXIT event to be generated because the current event
4375 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004376 */
4377TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4378 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4379 sp<FakeWindowHandle> window =
4380 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4381 window->setFrame(Rect(0, 0, 100, 100));
4382
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004383 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004384 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4385 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4386 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004387 ASSERT_NO_FATAL_FAILURE(
4388 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4389 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004390
4391 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004392 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4393 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4394 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004395 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004396 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4397 WithSource(AINPUT_SOURCE_MOUSE))));
4398
4399 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004400 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4401 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4402
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004403 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4404 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4405 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004406 ASSERT_NO_FATAL_FAILURE(
4407 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4408 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4409}
4410
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004411TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4412 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4413 sp<FakeWindowHandle> windowDefaultDisplay =
4414 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4415 ADISPLAY_ID_DEFAULT);
4416 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4417 sp<FakeWindowHandle> windowSecondDisplay =
4418 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4419 SECOND_DISPLAY_ID);
4420 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4421
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004422 mDispatcher->onWindowInfosChanged(
4423 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004424
4425 // Set cursor position in window in default display and check that hover enter and move
4426 // events are generated.
4427 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004428 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004429 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4430 AINPUT_SOURCE_MOUSE)
4431 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004432 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004433 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004434 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004435
4436 // Remove all windows in secondary display and check that no event happens on window in
4437 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004438 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4439
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004440 windowDefaultDisplay->assertNoEvents();
4441
4442 // Move cursor position in window in default display and check that only hover move
4443 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004444 mDispatcher->onWindowInfosChanged(
4445 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004446 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004447 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004448 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4449 AINPUT_SOURCE_MOUSE)
4450 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004451 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004452 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004453 windowDefaultDisplay->consumeMotionEvent(
4454 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4455 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004456 windowDefaultDisplay->assertNoEvents();
4457}
4458
Garfield Tan00f511d2019-06-12 16:55:40 -07004459TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004460 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004461
4462 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004463 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004464 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004465 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004466 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004467 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004468
4469 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4470
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004471 mDispatcher->onWindowInfosChanged(
4472 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004473
4474 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4475 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004476 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004477 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004478 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004479 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004480 windowRight->assertNoEvents();
4481}
4482
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004483TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004484 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004485 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4486 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004487 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004488
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004489 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004490 setFocusedWindow(window);
4491
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004492 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004493
Prabir Pradhan678438e2023-04-13 19:32:51 +00004494 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004495
4496 // Window should receive key down event.
4497 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4498
4499 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4500 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004501 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004502 window->consumeKeyUp(ADISPLAY_ID_DEFAULT, AKEY_EVENT_FLAG_CANCELED);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004503}
4504
4505TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004506 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004507 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4508 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004509
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004510 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004511
Prabir Pradhan678438e2023-04-13 19:32:51 +00004512 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4513 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004514
4515 // Window should receive motion down event.
4516 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4517
4518 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4519 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004520 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004521 window->consumeMotionEvent(
4522 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004523}
4524
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004525TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4526 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4527 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4528 "Fake Window", ADISPLAY_ID_DEFAULT);
4529
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004530 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004531
4532 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4533 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4534 .build());
4535
4536 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4537
4538 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4539 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4540 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4541
4542 // After the device has been reset, a new hovering stream can be sent to the window
4543 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4544 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4545 .build());
4546 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4547}
4548
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004549TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4550 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004551 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4552 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004553 window->setFocusable(true);
4554
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004555 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004556 setFocusedWindow(window);
4557
4558 window->consumeFocusEvent(true);
4559
Prabir Pradhan678438e2023-04-13 19:32:51 +00004560 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004561 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4562 const nsecs_t injectTime = keyArgs.eventTime;
4563 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004564 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004565 // The dispatching time should be always greater than or equal to intercept key timeout.
4566 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4567 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4568 std::chrono::nanoseconds(interceptKeyTimeout).count());
4569}
4570
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004571/**
4572 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4573 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004574TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4575 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004576 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4577 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004578 window->setFocusable(true);
4579
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004580 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004581 setFocusedWindow(window);
4582
4583 window->consumeFocusEvent(true);
4584
Prabir Pradhan678438e2023-04-13 19:32:51 +00004585 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004586 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004587
4588 // Set a value that's significantly larger than the default consumption timeout. If the
4589 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4590 mFakePolicy->setInterceptKeyTimeout(600ms);
4591 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4592 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004593 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4594}
4595
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004596/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004597 * Two windows. First is a regular window. Second does not overlap with the first, and has
4598 * WATCH_OUTSIDE_TOUCH.
4599 * Both windows are owned by the same UID.
4600 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4601 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4602 */
4603TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4604 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004605 sp<FakeWindowHandle> window =
4606 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004607 window->setFrame(Rect{0, 0, 100, 100});
4608
4609 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004610 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004611 ADISPLAY_ID_DEFAULT);
4612 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4613 outsideWindow->setWatchOutsideTouch(true);
4614 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004615 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004616
4617 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004618 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4619 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4620 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004621 window->consumeMotionDown();
4622 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4623 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4624 outsideWindow->consumeMotionEvent(
4625 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00004626
4627 // Ensure outsideWindow doesn't get any more events for the gesture.
4628 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4629 ADISPLAY_ID_DEFAULT, {PointF{51, 51}}));
4630 window->consumeMotionMove();
4631 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004632}
4633
4634/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004635 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4636 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4637 * ACTION_OUTSIDE event is sent per gesture.
4638 */
4639TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4640 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4641 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004642 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4643 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004644 window->setWatchOutsideTouch(true);
4645 window->setFrame(Rect{0, 0, 100, 100});
4646 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004647 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4648 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004649 secondWindow->setFrame(Rect{100, 100, 200, 200});
4650 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004651 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4652 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004653 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004654 mDispatcher->onWindowInfosChanged(
4655 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004656
4657 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004658 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4659 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4660 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004661 window->assertNoEvents();
4662 secondWindow->assertNoEvents();
4663
4664 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4665 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004666 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4667 ADISPLAY_ID_DEFAULT,
4668 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004669 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4670 window->consumeMotionEvent(
4671 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004672 secondWindow->consumeMotionDown();
4673 thirdWindow->assertNoEvents();
4674
4675 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4676 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004677 mDispatcher->notifyMotion(
4678 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4679 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004680 window->assertNoEvents();
4681 secondWindow->consumeMotionMove();
4682 thirdWindow->consumeMotionDown();
4683}
4684
Prabir Pradhan814fe082022-07-22 20:22:18 +00004685TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4686 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004687 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4688 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004689 window->setFocusable(true);
4690
Patrick Williamsd828f302023-04-28 17:52:08 -05004691 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004692 setFocusedWindow(window);
4693
4694 window->consumeFocusEvent(true);
4695
Prabir Pradhan678438e2023-04-13 19:32:51 +00004696 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4697 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4698 mDispatcher->notifyKey(keyDown);
4699 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004700
4701 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4702 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4703
4704 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004705 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004706
4707 window->consumeFocusEvent(false);
4708
Prabir Pradhan678438e2023-04-13 19:32:51 +00004709 mDispatcher->notifyKey(keyDown);
4710 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004711 window->assertNoEvents();
4712}
4713
Arthur Hung96483742022-11-15 03:30:48 +00004714TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4715 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4716 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4717 "Fake Window", ADISPLAY_ID_DEFAULT);
4718 // Ensure window is non-split and have some transform.
4719 window->setPreventSplitting(true);
4720 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004721 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004722
4723 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004724 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004725 {50, 50}))
4726 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4727 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4728
4729 const MotionEvent secondFingerDownEvent =
4730 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4731 .displayId(ADISPLAY_ID_DEFAULT)
4732 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004733 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4734 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004735 .build();
4736 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004737 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004738 InputEventInjectionSync::WAIT_FOR_RESULT))
4739 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4740
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004741 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
4742 ASSERT_NE(nullptr, event);
Arthur Hung96483742022-11-15 03:30:48 +00004743 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4744 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4745 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4746 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4747 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
4748}
4749
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004750/**
4751 * Two windows: a splittable and a non-splittable.
4752 * The non-splittable window shouldn't receive any "incomplete" gestures.
4753 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4754 * The second pointer should be dropped because the initial window is splittable, so it won't get
4755 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4756 * "incomplete" gestures.
4757 */
4758TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4759 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4760 sp<FakeWindowHandle> leftWindow =
4761 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4762 ADISPLAY_ID_DEFAULT);
4763 leftWindow->setPreventSplitting(false);
4764 leftWindow->setFrame(Rect(0, 0, 100, 100));
4765 sp<FakeWindowHandle> rightWindow =
4766 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4767 ADISPLAY_ID_DEFAULT);
4768 rightWindow->setPreventSplitting(true);
4769 rightWindow->setFrame(Rect(100, 100, 200, 200));
4770 mDispatcher->onWindowInfosChanged(
4771 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4772
4773 // Touch down on left, splittable window
4774 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4775 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4776 .build());
4777 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4778
4779 mDispatcher->notifyMotion(
4780 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4781 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4782 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4783 .build());
4784 leftWindow->assertNoEvents();
4785 rightWindow->assertNoEvents();
4786}
4787
Siarhei Vishniakou9b849a72024-07-15 18:11:27 +00004788/**
4789 * Two windows: left and right. The left window has PREVENT_SPLITTING input config. Device A sends a
4790 * down event to the right window. Device B sends a down event to the left window, and then a
4791 * POINTER_DOWN event to the right window. However, since the left window prevents splitting, the
4792 * POINTER_DOWN event should only go to the left window, and not to the right window.
4793 * This test attempts to reproduce a crash.
4794 */
4795TEST_F(InputDispatcherTest, MultiDeviceTwoWindowsPreventSplitting) {
4796 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4797 sp<FakeWindowHandle> leftWindow =
4798 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window (prevent splitting)",
4799 ADISPLAY_ID_DEFAULT);
4800 leftWindow->setFrame(Rect(0, 0, 100, 100));
4801 leftWindow->setPreventSplitting(true);
4802
4803 sp<FakeWindowHandle> rightWindow =
4804 sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
4805 ADISPLAY_ID_DEFAULT);
4806 rightWindow->setFrame(Rect(100, 0, 200, 100));
4807
4808 mDispatcher->onWindowInfosChanged(
4809 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4810
4811 const DeviceId deviceA = 9;
4812 const DeviceId deviceB = 3;
4813 // Touch the right window with device A
4814 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4815 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
4816 .deviceId(deviceA)
4817 .build());
4818 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
4819 // Touch the left window with device B
4820 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4821 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4822 .deviceId(deviceB)
4823 .build());
4824 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
4825 // Send a second pointer from device B to the right window. It shouldn't go to the right window
4826 // because the left window prevents splitting.
4827 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4828 .deviceId(deviceB)
4829 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4830 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4831 .build());
4832 leftWindow->consumeMotionPointerDown(1, WithDeviceId(deviceB));
4833
4834 // Finish the gesture for both devices
4835 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4836 .deviceId(deviceB)
4837 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4838 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4839 .build());
4840 leftWindow->consumeMotionPointerUp(1, WithDeviceId(deviceB));
4841 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4842 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4843 .deviceId(deviceB)
4844 .build());
4845 leftWindow->consumeMotionEvent(
4846 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceB), WithPointerId(0, 0)));
4847 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4848 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
4849 .deviceId(deviceA)
4850 .build());
4851 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceA)));
4852}
4853
Harry Cuttsb166c002023-05-09 13:06:05 +00004854TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4855 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4856 sp<FakeWindowHandle> window =
4857 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4858 window->setFrame(Rect(0, 0, 400, 400));
4859 sp<FakeWindowHandle> trustedOverlay =
4860 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4861 ADISPLAY_ID_DEFAULT);
4862 trustedOverlay->setSpy(true);
4863 trustedOverlay->setTrustedOverlay(true);
4864
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004865 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004866
4867 // Start a three-finger touchpad swipe
4868 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4869 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4870 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4871 .build());
4872 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4873 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4874 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4875 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4876 .build());
4877 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4878 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4879 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4880 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4881 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4882 .build());
4883
4884 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4885 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4886 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4887
4888 // Move the swipe a bit
4889 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4890 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4891 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4892 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4893 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4894 .build());
4895
4896 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4897
4898 // End the swipe
4899 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4900 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4901 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4902 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4903 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4904 .build());
4905 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4906 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4907 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4908 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4909 .build());
4910 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4911 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4912 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4913 .build());
4914
4915 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4916 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4917 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4918
4919 window->assertNoEvents();
4920}
4921
4922TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4923 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4924 sp<FakeWindowHandle> window =
4925 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4926 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004927 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004928
4929 // Start a three-finger touchpad swipe
4930 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4931 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4932 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4933 .build());
4934 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4935 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4936 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4937 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4938 .build());
4939 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4940 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4941 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4942 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4943 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4944 .build());
4945
4946 // Move the swipe a bit
4947 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4948 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4949 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4950 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4951 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4952 .build());
4953
4954 // End the swipe
4955 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4956 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4957 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4958 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4959 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4960 .build());
4961 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4962 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4963 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4964 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4965 .build());
4966 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4967 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4968 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4969 .build());
4970
4971 window->assertNoEvents();
4972}
4973
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004974/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004975 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4976 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004977 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004978 */
4979TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4980 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4981 sp<FakeWindowHandle> window =
4982 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4983 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004984 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004985
4986 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4987 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4988 .downTime(baseTime + 10)
4989 .eventTime(baseTime + 10)
4990 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4991 .build());
4992
4993 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4994
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004995 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004996 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004997
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004998 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004999
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005000 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5001 .downTime(baseTime + 10)
5002 .eventTime(baseTime + 30)
5003 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5004 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
5005 .build());
5006
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005007 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
5008
5009 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005010 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
5011 .downTime(baseTime + 10)
5012 .eventTime(baseTime + 40)
5013 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5014 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
5015 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005016
5017 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
5018
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005019 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5020 .downTime(baseTime + 10)
5021 .eventTime(baseTime + 50)
5022 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5023 .build());
5024
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005025 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
5026
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005027 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5028 .downTime(baseTime + 60)
5029 .eventTime(baseTime + 60)
5030 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
5031 .build());
5032
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005033 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005034}
5035
5036/**
Hu Guo771a7692023-09-17 20:51:08 +08005037 * When there are multiple screens, such as screen projection to TV or screen recording, if the
5038 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
5039 * its coordinates should be converted by the transform of the windows of target screen.
5040 */
5041TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
5042 // This case will create a window and a spy window on the default display and mirror
5043 // window on the second display. cancel event is sent through spy window pilferPointers
5044 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5045
5046 sp<FakeWindowHandle> spyWindowDefaultDisplay =
5047 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
5048 spyWindowDefaultDisplay->setTrustedOverlay(true);
5049 spyWindowDefaultDisplay->setSpy(true);
5050
5051 sp<FakeWindowHandle> windowDefaultDisplay =
5052 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
5053 ADISPLAY_ID_DEFAULT);
5054 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
5055
5056 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
5057 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
5058
5059 // Add the windows to the dispatcher
5060 mDispatcher->onWindowInfosChanged(
5061 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
5062 *windowSecondDisplay->getInfo()},
5063 {},
5064 0,
5065 0});
5066
5067 // Send down to ADISPLAY_ID_DEFAULT
5068 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5069 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5070 {100, 100}))
5071 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5072
5073 spyWindowDefaultDisplay->consumeMotionDown();
5074 windowDefaultDisplay->consumeMotionDown();
5075
5076 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
5077
5078 // windowDefaultDisplay gets cancel
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005079 std::unique_ptr<MotionEvent> event = windowDefaultDisplay->consumeMotionEvent();
5080 ASSERT_NE(nullptr, event);
Hu Guo771a7692023-09-17 20:51:08 +08005081 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
5082
5083 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
5084 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
5085 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
5086 // SECOND_DISPLAY_ID, the x and y coordinates are 200
5087 EXPECT_EQ(100, event->getX(0));
5088 EXPECT_EQ(100, event->getY(0));
5089}
5090
5091/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005092 * Ensure the correct coordinate spaces are used by InputDispatcher.
5093 *
5094 * InputDispatcher works in the display space, so its coordinate system is relative to the display
5095 * panel. Windows get events in the window space, and get raw coordinates in the logical display
5096 * space.
5097 */
5098class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
5099public:
5100 void SetUp() override {
5101 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005102 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005103 }
5104
5105 void addDisplayInfo(int displayId, const ui::Transform& transform) {
5106 gui::DisplayInfo info;
5107 info.displayId = displayId;
5108 info.transform = transform;
5109 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05005110 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005111 }
5112
5113 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
5114 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05005115 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005116 }
5117
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005118 void removeAllWindowsAndDisplays() {
5119 mDisplayInfos.clear();
5120 mWindowInfos.clear();
5121 }
5122
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005123 // Set up a test scenario where the display has a scaled projection and there are two windows
5124 // on the display.
5125 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
5126 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
5127 // respectively.
5128 ui::Transform displayTransform;
5129 displayTransform.set(2, 0, 0, 4);
5130 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5131
5132 std::shared_ptr<FakeApplicationHandle> application =
5133 std::make_shared<FakeApplicationHandle>();
5134
5135 // Add two windows to the display. Their frames are represented in the display space.
5136 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005137 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5138 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005139 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
5140 addWindow(firstWindow);
5141
5142 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005143 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5144 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005145 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
5146 addWindow(secondWindow);
5147 return {std::move(firstWindow), std::move(secondWindow)};
5148 }
5149
5150private:
5151 std::vector<gui::DisplayInfo> mDisplayInfos;
5152 std::vector<gui::WindowInfo> mWindowInfos;
5153};
5154
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005155TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005156 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5157 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005158 // selected so that if the hit test was performed with the point and the bounds being in
5159 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005160 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5161 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5162 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005163
5164 firstWindow->consumeMotionDown();
5165 secondWindow->assertNoEvents();
5166}
5167
5168// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
5169// the event should be treated as being in the logical display space.
5170TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
5171 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5172 // Send down to the first window. The point is represented in the logical display space. The
5173 // point is selected so that if the hit test was done in logical display space, then it would
5174 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005175 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005176 PointF{75 * 2, 55 * 4});
5177
5178 firstWindow->consumeMotionDown();
5179 secondWindow->assertNoEvents();
5180}
5181
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005182// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
5183// event should be treated as being in the logical display space.
5184TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
5185 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5186
5187 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5188 ui::Transform injectedEventTransform;
5189 injectedEventTransform.set(matrix);
5190 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
5191 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
5192
5193 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5194 .displayId(ADISPLAY_ID_DEFAULT)
5195 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005196 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005197 .x(untransformedPoint.x)
5198 .y(untransformedPoint.y))
5199 .build();
5200 event.transform(matrix);
5201
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005202 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005203 InputEventInjectionSync::WAIT_FOR_RESULT);
5204
5205 firstWindow->consumeMotionDown();
5206 secondWindow->assertNoEvents();
5207}
5208
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005209TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
5210 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5211
5212 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005213 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5214 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5215 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005216
5217 firstWindow->assertNoEvents();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005218 std::unique_ptr<MotionEvent> event = secondWindow->consumeMotionEvent();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07005219 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005220 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
5221
5222 // Ensure that the events from the "getRaw" API are in logical display coordinates.
5223 EXPECT_EQ(300, event->getRawX(0));
5224 EXPECT_EQ(880, event->getRawY(0));
5225
5226 // Ensure that the x and y values are in the window's coordinate space.
5227 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
5228 // the logical display space. This will be the origin of the window space.
5229 EXPECT_EQ(100, event->getX(0));
5230 EXPECT_EQ(80, event->getY(0));
5231}
5232
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005233TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
5234 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5235 // The monitor will always receive events in the logical display's coordinate space, because
5236 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00005237 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005238
5239 // Send down to the first window.
5240 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5241 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5242 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5243 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5244
5245 // Second pointer goes down on second window.
5246 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5247 ADISPLAY_ID_DEFAULT,
5248 {PointF{50, 100}, PointF{150, 220}}));
5249 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
5250 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
5251 {1, PointF{300, 880}}};
5252 monitor.consumeMotionEvent(
5253 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
5254
5255 mDispatcher->cancelCurrentTouch();
5256
5257 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5258 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
5259 monitor.consumeMotionEvent(
5260 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
5261}
5262
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005263TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
5264 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5265
5266 // Send down to the first window.
5267 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5268 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5269 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5270
5271 // The pointer is transferred to the second window, and the second window receives it in the
5272 // correct coordinate space.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005273 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005274 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5275 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
5276}
5277
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005278TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
5279 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5280
5281 // Send hover move to the second window, and ensure it shows up as hover enter.
5282 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5283 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5284 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5285 WithCoords(100, 80), WithRawCoords(300, 880)));
5286
5287 // Touch down at the same location and ensure a hover exit is synthesized.
5288 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5289 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5290 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5291 WithRawCoords(300, 880)));
5292 secondWindow->consumeMotionEvent(
5293 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5294 secondWindow->assertNoEvents();
5295 firstWindow->assertNoEvents();
5296}
5297
Prabir Pradhan453ae732023-10-13 14:30:14 +00005298// Same as above, but while the window is being mirrored.
5299TEST_F(InputDispatcherDisplayProjectionTest,
5300 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
5301 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5302
5303 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5304 ui::Transform secondDisplayTransform;
5305 secondDisplayTransform.set(matrix);
5306 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5307
5308 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5309 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5310 addWindow(secondWindowClone);
5311
5312 // Send hover move to the second window, and ensure it shows up as hover enter.
5313 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5314 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5315 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5316 WithCoords(100, 80), WithRawCoords(300, 880)));
5317
5318 // Touch down at the same location and ensure a hover exit is synthesized for the correct
5319 // display.
5320 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5321 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5322 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5323 WithRawCoords(300, 880)));
5324 secondWindow->consumeMotionEvent(
5325 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5326 secondWindow->assertNoEvents();
5327 firstWindow->assertNoEvents();
5328}
5329
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005330TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
5331 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5332
5333 // Send hover enter to second window
5334 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5335 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5336 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5337 WithCoords(100, 80), WithRawCoords(300, 880)));
5338
5339 mDispatcher->cancelCurrentTouch();
5340
5341 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5342 WithRawCoords(300, 880)));
5343 secondWindow->assertNoEvents();
5344 firstWindow->assertNoEvents();
5345}
5346
Prabir Pradhan453ae732023-10-13 14:30:14 +00005347// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00005348TEST_F(InputDispatcherDisplayProjectionTest,
5349 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
5350 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5351
5352 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5353 ui::Transform secondDisplayTransform;
5354 secondDisplayTransform.set(matrix);
5355 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5356
5357 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5358 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5359 addWindow(secondWindowClone);
5360
5361 // Send hover enter to second window
5362 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5363 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5364 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5365 WithCoords(100, 80), WithRawCoords(300, 880),
5366 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5367
5368 mDispatcher->cancelCurrentTouch();
5369
5370 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
5371 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5372 WithRawCoords(300, 880),
5373 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5374 secondWindow->assertNoEvents();
5375 firstWindow->assertNoEvents();
5376}
5377
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005378/** Ensure consistent behavior of InputDispatcher in all orientations. */
5379class InputDispatcherDisplayOrientationFixture
5380 : public InputDispatcherDisplayProjectionTest,
5381 public ::testing::WithParamInterface<ui::Rotation> {};
5382
5383// This test verifies the touchable region of a window for all rotations of the display by tapping
5384// in different locations on the display, specifically points close to the four corners of a
5385// window.
5386TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
5387 constexpr static int32_t displayWidth = 400;
5388 constexpr static int32_t displayHeight = 800;
5389
5390 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5391
5392 const auto rotation = GetParam();
5393
5394 // Set up the display with the specified rotation.
5395 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5396 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5397 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5398 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5399 logicalDisplayWidth, logicalDisplayHeight);
5400 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5401
5402 // Create a window with its bounds determined in the logical display.
5403 const Rect frameInLogicalDisplay(100, 100, 200, 300);
5404 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
5405 sp<FakeWindowHandle> window =
5406 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5407 window->setFrame(frameInDisplay, displayTransform);
5408 addWindow(window);
5409
5410 // The following points in logical display space should be inside the window.
5411 static const std::array<vec2, 4> insidePoints{
5412 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5413 for (const auto pointInsideWindow : insidePoints) {
5414 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
5415 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005416 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5417 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5418 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005419 window->consumeMotionDown();
5420
Prabir Pradhan678438e2023-04-13 19:32:51 +00005421 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5422 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5423 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005424 window->consumeMotionUp();
5425 }
5426
5427 // The following points in logical display space should be outside the window.
5428 static const std::array<vec2, 5> outsidePoints{
5429 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
5430 for (const auto pointOutsideWindow : outsidePoints) {
5431 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
5432 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005433 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5434 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5435 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005436
Prabir Pradhan678438e2023-04-13 19:32:51 +00005437 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5438 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5439 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005440 }
5441 window->assertNoEvents();
5442}
5443
5444// Run the precision tests for all rotations.
5445INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
5446 InputDispatcherDisplayOrientationFixture,
5447 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
5448 ui::ROTATION_270),
5449 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
5450 return ftl::enum_string(testParamInfo.param);
5451 });
5452
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005453using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
5454 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005455
5456class TransferTouchFixture : public InputDispatcherTest,
5457 public ::testing::WithParamInterface<TransferFunction> {};
5458
5459TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07005460 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005461
5462 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005463 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005464 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5465 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005466 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005467 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005468 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5469 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005470 sp<FakeWindowHandle> wallpaper =
5471 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
5472 wallpaper->setIsWallpaper(true);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005473 // Add the windows to the dispatcher, and ensure the first window is focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005474 mDispatcher->onWindowInfosChanged(
5475 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Prabir Pradhan65455c72024-02-13 21:46:41 +00005476 setFocusedWindow(firstWindow);
5477 firstWindow->consumeFocusEvent(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005478
5479 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005480 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5481 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005482
Svet Ganov5d3bc372020-01-26 23:11:07 -08005483 // Only the first window should get the down event
5484 firstWindow->consumeMotionDown();
5485 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005486 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005487 // Dispatcher reports pointer down outside focus for the wallpaper
5488 mFakePolicy->assertOnPointerDownEquals(wallpaper->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08005489
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005490 // Transfer touch to the second window
5491 TransferFunction f = GetParam();
5492 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5493 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005494 // The first window gets cancel and the second gets down
5495 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005496 secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005497 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005498 // There should not be any changes to the focused window when transferring touch
5499 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertOnPointerDownWasNotCalled());
Svet Ganov5d3bc372020-01-26 23:11:07 -08005500
5501 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005502 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5503 ADISPLAY_ID_DEFAULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +00005504 // The first window gets no events and the second gets up
Svet Ganov5d3bc372020-01-26 23:11:07 -08005505 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005506 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005507 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005508}
5509
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005510/**
Prabir Pradhan367f3432024-02-13 23:05:58 +00005511 * When 'transferTouchGesture' API is invoked, dispatcher needs to find the "best" window to take
5512 * touch from. When we have spy windows, there are several windows to choose from: either spy, or
5513 * the 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005514 * natural to the user.
5515 * In this test, we are sending a pointer to both spy window and first window. We then try to
5516 * transfer touch to the second window. The dispatcher should identify the first window as the
5517 * one that should lose the gesture, and therefore the action should be to move the gesture from
5518 * the first window to the second.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005519 * The main goal here is to test the behaviour of 'transferTouchGesture' API, but it's still valid
5520 * to test the other API, as well.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005521 */
5522TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5523 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5524
5525 // Create a couple of windows + a spy window
5526 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005527 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005528 spyWindow->setTrustedOverlay(true);
5529 spyWindow->setSpy(true);
5530 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005531 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005532 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005533 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005534
5535 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005536 mDispatcher->onWindowInfosChanged(
5537 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005538
5539 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005540 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5541 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005542 // Only the first window and spy should get the down event
5543 spyWindow->consumeMotionDown();
5544 firstWindow->consumeMotionDown();
5545
5546 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
Prabir Pradhan367f3432024-02-13 23:05:58 +00005547 // if f === 'transferTouchGesture'.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005548 TransferFunction f = GetParam();
5549 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5550 ASSERT_TRUE(success);
5551 // The first window gets cancel and the second gets down
5552 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005553 secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005554
5555 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005556 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5557 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005558 // The first window gets no events and the second+spy get up
5559 firstWindow->assertNoEvents();
5560 spyWindow->consumeMotionUp();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005561 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005562}
5563
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005564TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005565 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005566
5567 PointF touchPoint = {10, 10};
5568
5569 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005570 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005571 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5572 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005573 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005574 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005575 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5576 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005577 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005578
5579 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005580 mDispatcher->onWindowInfosChanged(
5581 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005582
5583 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005584 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5585 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5586 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005587 // Only the first window should get the down event
5588 firstWindow->consumeMotionDown();
5589 secondWindow->assertNoEvents();
5590
5591 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005592 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5593 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005594 // Only the first window should get the pointer down event
5595 firstWindow->consumeMotionPointerDown(1);
5596 secondWindow->assertNoEvents();
5597
5598 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005599 TransferFunction f = GetParam();
5600 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5601 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005602 // The first window gets cancel and the second gets down and pointer down
5603 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005604 secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
5605 secondWindow->consumeMotionPointerDown(1, ADISPLAY_ID_DEFAULT,
5606 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005607
5608 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005609 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5610 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005611 // The first window gets nothing and the second gets pointer up
5612 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005613 secondWindow->consumeMotionPointerUp(1, ADISPLAY_ID_DEFAULT,
5614 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005615
5616 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005617 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5618 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005619 // The first window gets nothing and the second gets up
5620 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005621 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005622}
5623
Arthur Hungc539dbb2022-12-08 07:45:36 +00005624TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5625 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5626
5627 // Create a couple of windows
5628 sp<FakeWindowHandle> firstWindow =
5629 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5630 ADISPLAY_ID_DEFAULT);
5631 firstWindow->setDupTouchToWallpaper(true);
5632 sp<FakeWindowHandle> secondWindow =
5633 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5634 ADISPLAY_ID_DEFAULT);
5635 secondWindow->setDupTouchToWallpaper(true);
5636
5637 sp<FakeWindowHandle> wallpaper1 =
5638 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5639 wallpaper1->setIsWallpaper(true);
5640
5641 sp<FakeWindowHandle> wallpaper2 =
5642 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5643 wallpaper2->setIsWallpaper(true);
5644 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005645 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5646 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5647 {},
5648 0,
5649 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005650
5651 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005652 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5653 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005654
5655 // Only the first window should get the down event
5656 firstWindow->consumeMotionDown();
5657 secondWindow->assertNoEvents();
5658 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5659 wallpaper2->assertNoEvents();
5660
5661 // Transfer touch focus to the second window
5662 TransferFunction f = GetParam();
5663 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5664 ASSERT_TRUE(success);
5665
5666 // The first window gets cancel and the second gets down
5667 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005668 secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005669 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005670 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5671 expectedWallpaperFlags | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005672
5673 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005674 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5675 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005676 // The first window gets no events and the second gets up
5677 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005678 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005679 wallpaper1->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005680 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT,
5681 expectedWallpaperFlags | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005682}
5683
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005684// For the cases of single pointer touch and two pointers non-split touch, the api's
Prabir Pradhan367f3432024-02-13 23:05:58 +00005685// 'transferTouchGesture' and 'transferTouchOnDisplay' are equivalent in behaviour. They only differ
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005686// for the case where there are multiple pointers split across several windows.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005687INSTANTIATE_TEST_SUITE_P(
5688 InputDispatcherTransferFunctionTests, TransferTouchFixture,
5689 ::testing::Values(
5690 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> /*ignored*/,
5691 sp<IBinder> destChannelToken) {
5692 return dispatcher->transferTouchOnDisplay(destChannelToken,
5693 ADISPLAY_ID_DEFAULT);
5694 },
5695 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> from,
5696 sp<IBinder> to) {
5697 return dispatcher->transferTouchGesture(from, to,
5698 /*isDragAndDrop=*/false);
5699 }));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005700
Prabir Pradhan367f3432024-02-13 23:05:58 +00005701TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005702 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005703
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005704 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005705 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5706 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005707 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005708
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005709 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005710 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5711 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005712 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005713
5714 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005715 mDispatcher->onWindowInfosChanged(
5716 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005717
5718 PointF pointInFirst = {300, 200};
5719 PointF pointInSecond = {300, 600};
5720
5721 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005722 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5723 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5724 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005725 // Only the first window should get the down event
5726 firstWindow->consumeMotionDown();
5727 secondWindow->assertNoEvents();
5728
5729 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005730 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5731 ADISPLAY_ID_DEFAULT,
5732 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005733 // The first window gets a move and the second a down
5734 firstWindow->consumeMotionMove();
5735 secondWindow->consumeMotionDown();
5736
Prabir Pradhan367f3432024-02-13 23:05:58 +00005737 // Transfer touch to the second window
5738 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08005739 // The first window gets cancel and the new gets pointer down (it already saw down)
5740 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005741 secondWindow->consumeMotionPointerDown(1, ADISPLAY_ID_DEFAULT,
5742 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005743
5744 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005745 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5746 ADISPLAY_ID_DEFAULT,
5747 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005748 // The first window gets nothing and the second gets pointer up
5749 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005750 secondWindow->consumeMotionPointerUp(1, ADISPLAY_ID_DEFAULT,
5751 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005752
5753 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005754 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5755 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005756 // The first window gets nothing and the second gets up
5757 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005758 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005759}
5760
Prabir Pradhan367f3432024-02-13 23:05:58 +00005761// Same as TransferTouch_TwoPointersSplitTouch, but using 'transferTouchOnDisplay' api.
5762// Unlike 'transferTouchGesture', calling 'transferTouchOnDisplay' when there are two windows
5763// receiving touch is not supported, so the touch should continue on those windows and the
5764// transferred-to window should get nothing.
5765TEST_F(InputDispatcherTest, TransferTouchOnDisplay_TwoPointersSplitTouch) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005766 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5767
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005768 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005769 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5770 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005771 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005772
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005773 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005774 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5775 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005776 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005777
5778 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005779 mDispatcher->onWindowInfosChanged(
5780 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005781
5782 PointF pointInFirst = {300, 200};
5783 PointF pointInSecond = {300, 600};
5784
5785 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005786 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5787 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5788 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005789 // Only the first window should get the down event
5790 firstWindow->consumeMotionDown();
5791 secondWindow->assertNoEvents();
5792
5793 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005794 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5795 ADISPLAY_ID_DEFAULT,
5796 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005797 // The first window gets a move and the second a down
5798 firstWindow->consumeMotionMove();
5799 secondWindow->consumeMotionDown();
5800
5801 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005802 const bool transferred =
Prabir Pradhan367f3432024-02-13 23:05:58 +00005803 mDispatcher->transferTouchOnDisplay(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
5804 // The 'transferTouchOnDisplay' call should not succeed, because there are 2 touched windows
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005805 ASSERT_FALSE(transferred);
5806 firstWindow->assertNoEvents();
5807 secondWindow->assertNoEvents();
5808
5809 // The rest of the dispatch should proceed as normal
5810 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005811 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5812 ADISPLAY_ID_DEFAULT,
5813 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005814 // The first window gets MOVE and the second gets pointer up
5815 firstWindow->consumeMotionMove();
5816 secondWindow->consumeMotionUp();
5817
5818 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005819 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5820 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005821 // The first window gets nothing and the second gets up
5822 firstWindow->consumeMotionUp();
5823 secondWindow->assertNoEvents();
5824}
5825
Arthur Hungabbb9d82021-09-01 14:52:30 +00005826// This case will create two windows and one mirrored window on the default display and mirror
Prabir Pradhan367f3432024-02-13 23:05:58 +00005827// two windows on the second display. It will test if 'transferTouchGesture' works fine if we put
Arthur Hungabbb9d82021-09-01 14:52:30 +00005828// the windows info of second display before default display.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005829TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00005830 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5831 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005832 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005833 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005834 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005835 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005836 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005837
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005838 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005839 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005840
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005841 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005842 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005843
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005844 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005845 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005846
5847 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005848 mDispatcher->onWindowInfosChanged(
5849 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5850 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5851 *secondWindowInPrimary->getInfo()},
5852 {},
5853 0,
5854 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005855
5856 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005857 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005858 {50, 50}))
5859 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5860
5861 // Window should receive motion event.
5862 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5863
Prabir Pradhan367f3432024-02-13 23:05:58 +00005864 // Transfer touch
5865 ASSERT_TRUE(mDispatcher->transferTouchGesture(firstWindowInPrimary->getToken(),
5866 secondWindowInPrimary->getToken()));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005867 // The first window gets cancel.
5868 firstWindowInPrimary->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005869 secondWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5870 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005871
5872 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005873 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005874 ADISPLAY_ID_DEFAULT, {150, 50}))
5875 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5876 firstWindowInPrimary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005877 secondWindowInPrimary->consumeMotionMove(ADISPLAY_ID_DEFAULT,
5878 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005879
5880 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005881 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005882 {150, 50}))
5883 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5884 firstWindowInPrimary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005885 secondWindowInPrimary->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005886}
5887
Prabir Pradhan367f3432024-02-13 23:05:58 +00005888// Same as TransferTouch_CloneSurface, but this touch on the secondary display and use
5889// 'transferTouchOnDisplay' api.
5890TEST_F(InputDispatcherTest, TransferTouchOnDisplay_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00005891 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5892 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005893 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005894 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005895 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005896 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005897 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005898
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005899 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005900 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005901
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005902 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005903 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005904
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005905 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005906 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005907
5908 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005909 mDispatcher->onWindowInfosChanged(
5910 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5911 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5912 *secondWindowInPrimary->getInfo()},
5913 {},
5914 0,
5915 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005916
5917 // Touch on second display.
5918 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005919 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5920 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005921 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5922
5923 // Window should receive motion event.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005924 firstWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005925
5926 // Transfer touch focus
Prabir Pradhan367f3432024-02-13 23:05:58 +00005927 ASSERT_TRUE(mDispatcher->transferTouchOnDisplay(secondWindowInSecondary->getToken(),
5928 SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005929
5930 // The first window gets cancel.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005931 firstWindowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005932 secondWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID,
5933 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005934
5935 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005936 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005937 SECOND_DISPLAY_ID, {150, 50}))
5938 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005939 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005940 secondWindowInSecondary->consumeMotionMove(SECOND_DISPLAY_ID,
5941 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005942
5943 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005944 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005945 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005946 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005947 secondWindowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005948}
5949
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005950TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005951 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005952 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5953 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005954
Vishnu Nair47074b82020-08-14 11:54:47 -07005955 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005956 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005957 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005958
5959 window->consumeFocusEvent(true);
5960
Prabir Pradhan678438e2023-04-13 19:32:51 +00005961 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005962
5963 // Window should receive key down event.
5964 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005965
5966 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005967 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005968 mFakePolicy->assertUserActivityPoked();
5969}
5970
5971TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5972 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5973 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5974 "Fake Window", ADISPLAY_ID_DEFAULT);
5975
5976 window->setDisableUserActivity(true);
5977 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005978 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005979 setFocusedWindow(window);
5980
5981 window->consumeFocusEvent(true);
5982
5983 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5984
5985 // Window should receive key down event.
5986 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5987
5988 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005989 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005990 mFakePolicy->assertUserActivityNotPoked();
5991}
5992
5993TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5994 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5995 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5996 "Fake Window", ADISPLAY_ID_DEFAULT);
5997
5998 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005999 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00006000 setFocusedWindow(window);
6001
6002 window->consumeFocusEvent(true);
6003
6004 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
6005 mDispatcher->waitForIdle();
6006
6007 // System key is not passed down
6008 window->assertNoEvents();
6009
6010 // Should have poked user activity
6011 mFakePolicy->assertUserActivityPoked();
6012}
6013
6014TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
6015 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6016 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6017 "Fake Window", ADISPLAY_ID_DEFAULT);
6018
6019 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006020 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00006021 setFocusedWindow(window);
6022
6023 window->consumeFocusEvent(true);
6024
6025 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
6026 mDispatcher->waitForIdle();
6027
6028 // System key is not passed down
6029 window->assertNoEvents();
6030
6031 // Should have poked user activity
6032 mFakePolicy->assertUserActivityPoked();
6033}
6034
6035TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
6036 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6037 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6038 "Fake Window", ADISPLAY_ID_DEFAULT);
6039
6040 window->setDisableUserActivity(true);
6041 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006042 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00006043 setFocusedWindow(window);
6044
6045 window->consumeFocusEvent(true);
6046
6047 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
6048 mDispatcher->waitForIdle();
6049
6050 // System key is not passed down
6051 window->assertNoEvents();
6052
6053 // Should have poked user activity
6054 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006055}
6056
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006057TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
6058 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6059 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6060 "Fake Window", ADISPLAY_ID_DEFAULT);
6061
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006062 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006063
6064 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006065 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006066 ADISPLAY_ID_DEFAULT, {100, 100}))
6067 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6068
6069 window->consumeMotionEvent(
6070 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
6071
6072 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00006073 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006074 mFakePolicy->assertUserActivityPoked();
6075}
6076
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006077TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006078 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006079 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6080 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006081
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006082 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006083
Prabir Pradhan678438e2023-04-13 19:32:51 +00006084 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006085 mDispatcher->waitForIdle();
6086
6087 window->assertNoEvents();
6088}
6089
6090// If a window is touchable, but does not have focus, it should receive motion events, but not keys
6091TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07006092 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006093 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6094 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006095
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006096 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006097
6098 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00006099 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006100 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00006101 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6102 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006103
6104 // Window should receive only the motion event
6105 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6106 window->assertNoEvents(); // Key event or focus event will not be received
6107}
6108
arthurhungea3f4fc2020-12-21 23:18:53 +08006109TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
6110 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6111
arthurhungea3f4fc2020-12-21 23:18:53 +08006112 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006113 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
6114 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08006115 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08006116
arthurhungea3f4fc2020-12-21 23:18:53 +08006117 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006118 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
6119 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08006120 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08006121
6122 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006123 mDispatcher->onWindowInfosChanged(
6124 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08006125
6126 PointF pointInFirst = {300, 200};
6127 PointF pointInSecond = {300, 600};
6128
6129 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006130 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6131 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6132 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08006133 // Only the first window should get the down event
6134 firstWindow->consumeMotionDown();
6135 secondWindow->assertNoEvents();
6136
6137 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006138 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6139 ADISPLAY_ID_DEFAULT,
6140 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08006141 // The first window gets a move and the second a down
6142 firstWindow->consumeMotionMove();
6143 secondWindow->consumeMotionDown();
6144
6145 // Send pointer cancel to the second window
6146 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006147 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08006148 {pointInFirst, pointInSecond});
6149 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00006150 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08006151 // The first window gets move and the second gets cancel.
6152 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
6153 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
6154
6155 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00006156 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6157 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08006158 // The first window gets up and the second gets nothing.
6159 firstWindow->consumeMotionUp();
6160 secondWindow->assertNoEvents();
6161}
6162
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006163TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
6164 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6165
6166 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006167 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006168 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006169 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
6170 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
6171 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
6172
Harry Cutts33476232023-01-30 19:57:29 +00006173 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006174 window->assertNoEvents();
6175 mDispatcher->waitForIdle();
6176}
6177
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006178using InputDispatcherMonitorTest = InputDispatcherTest;
6179
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006180/**
6181 * Two entities that receive touch: A window, and a global monitor.
6182 * The touch goes to the window, and then the window disappears.
6183 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
6184 * for the monitor, as well.
6185 * 1. foregroundWindow
6186 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
6187 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006188TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006189 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6190 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006191 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006192
Prabir Pradhanfb549072023-10-05 19:17:36 +00006193 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006194
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006195 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006196 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006197 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006198 {100, 200}))
6199 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6200
6201 // Both the foreground window and the global monitor should receive the touch down
6202 window->consumeMotionDown();
6203 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6204
6205 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006206 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006207 ADISPLAY_ID_DEFAULT, {110, 200}))
6208 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6209
6210 window->consumeMotionMove();
6211 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6212
6213 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006214 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006215 window->consumeMotionCancel();
6216 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
6217
6218 // If more events come in, there will be no more foreground window to send them to. This will
6219 // cause a cancel for the monitor, as well.
6220 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006221 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006222 ADISPLAY_ID_DEFAULT, {120, 200}))
6223 << "Injection should fail because the window was removed";
6224 window->assertNoEvents();
6225 // Global monitor now gets the cancel
6226 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6227}
6228
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006229TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07006230 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006231 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6232 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006233 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006234
Prabir Pradhanfb549072023-10-05 19:17:36 +00006235 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006236
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006237 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006238 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006239 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00006240 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006241 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006242}
6243
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006244TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00006245 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006246
Chris Yea209fde2020-07-22 13:54:51 -07006247 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006248 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6249 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006250 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006251
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006252 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006253 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006254 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08006255 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006256 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006257
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006258 // Pilfer pointers from the monitor.
6259 // This should not do anything and the window should continue to receive events.
6260 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00006261
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006262 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006263 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006264 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006265 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006266
6267 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6268 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006269}
6270
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006271TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07006272 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006273 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6274 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006275 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07006276 window->setWindowOffset(20, 40);
6277 window->setWindowTransform(0, 1, -1, 0);
6278
Prabir Pradhanfb549072023-10-05 19:17:36 +00006279 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07006280
6281 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006282 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07006283 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6284 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006285 std::unique_ptr<MotionEvent> event = monitor.consumeMotion();
6286 ASSERT_NE(nullptr, event);
Evan Rosky84f07f02021-04-16 10:42:42 -07006287 // Even though window has transform, gesture monitor must not.
6288 ASSERT_EQ(ui::Transform(), event->getTransform());
6289}
6290
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006291TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00006292 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00006293 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00006294
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006295 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006296 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006297 << "Injection should fail if there is a monitor, but no touchable window";
6298 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00006299}
6300
Linnan Lid8150952024-01-26 18:07:17 +00006301/**
6302 * Two displays
6303 * The first monitor has a foreground window, a monitor
6304 * The second window has only one monitor.
6305 * We first inject a Down event into the first display, this injection should succeed and both
6306 * the foreground window and monitor should receive a down event, then inject a Down event into
6307 * the second display as well, this injection should fail, at this point, the first display
6308 * window and monitor should not receive a cancel or any other event.
6309 * Continue to inject Move and UP events to the first display, the events should be received
6310 * normally by the foreground window and monitor.
6311 */
6312TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCanceledWhenAnotherEmptyDisplayReceiveEvents) {
6313 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6314 sp<FakeWindowHandle> window =
6315 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6316
6317 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6318 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
6319
6320 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6321 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6322 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6323 {100, 200}))
6324 << "The down event injected into the first display should succeed";
6325
6326 window->consumeMotionDown();
6327 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006328
6329 ASSERT_EQ(InputEventInjectionResult::FAILED,
6330 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6331 {100, 200}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006332 << "The down event injected into the second display should fail since there's no "
6333 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006334
6335 // Continue to inject event to first display.
6336 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6337 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6338 ADISPLAY_ID_DEFAULT, {110, 220}))
6339 << "The move event injected into the first display should succeed";
6340
6341 window->consumeMotionMove();
6342 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006343
6344 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6345 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6346 {110, 220}))
6347 << "The up event injected into the first display should succeed";
6348
6349 window->consumeMotionUp();
6350 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006351
6352 window->assertNoEvents();
6353 monitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00006354 secondMonitor.assertNoEvents();
6355}
6356
6357/**
6358 * Two displays
6359 * There is a monitor and foreground window on each display.
6360 * First, we inject down events into each of the two displays, at this point, the foreground windows
6361 * and monitors on both displays should receive down events.
6362 * At this point, the foreground window of the second display goes away, the gone window should
6363 * receive the cancel event, and the other windows and monitors should not receive any events.
6364 * Inject a move event into the second display. At this point, the injection should fail because
6365 * the second display no longer has a foreground window. At this point, the monitor on the second
6366 * display should receive a cancel event, and any windows or monitors on the first display should
6367 * not receive any events, and any subsequent injection of events into the second display should
6368 * also fail.
6369 * Continue to inject events into the first display, and the events should all be injected
6370 * successfully and received normally.
6371 */
6372TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCancelWhenAnotherDisplayMonitorTouchCanceled) {
6373 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6374 sp<FakeWindowHandle> window =
6375 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6376 sp<FakeWindowHandle> secondWindow =
6377 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondForeground",
6378 SECOND_DISPLAY_ID);
6379
6380 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6381 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
6382
6383 // There is a foreground window on both displays.
6384 mDispatcher->onWindowInfosChanged({{*window->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
6385 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6386 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6387 {100, 200}))
6388 << "The down event injected into the first display should succeed";
6389
6390 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6391 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006392
6393 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6394 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6395 {100, 200}))
6396 << "The down event injected into the second display should succeed";
6397
Linnan Lid8150952024-01-26 18:07:17 +00006398 secondWindow->consumeMotionDown(SECOND_DISPLAY_ID);
6399 secondMonitor.consumeMotionDown(SECOND_DISPLAY_ID);
6400
6401 // Now second window is gone away.
6402 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6403
6404 // The gone window should receive a cancel, and the monitor on the second display should not
6405 // receive any events.
Linnan Lid8150952024-01-26 18:07:17 +00006406 secondWindow->consumeMotionCancel(SECOND_DISPLAY_ID);
6407 secondMonitor.assertNoEvents();
6408
6409 ASSERT_EQ(InputEventInjectionResult::FAILED,
6410 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6411 SECOND_DISPLAY_ID, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006412 << "The move event injected into the second display should fail because there's no "
6413 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006414 // Now the monitor on the second display should receive a cancel event.
6415 secondMonitor.consumeMotionCancel(SECOND_DISPLAY_ID);
Linnan Lid8150952024-01-26 18:07:17 +00006416
6417 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6418 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6419 ADISPLAY_ID_DEFAULT, {110, 200}))
6420 << "The move event injected into the first display should succeed";
6421
6422 window->consumeMotionMove();
6423 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006424
6425 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006426 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6427 {110, 220}))
6428 << "The up event injected into the second display should fail because there's no "
6429 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006430
6431 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6432 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6433 {110, 220}))
6434 << "The up event injected into the first display should succeed";
6435
6436 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6437 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006438
Linnan Lid8150952024-01-26 18:07:17 +00006439 window->assertNoEvents();
6440 monitor.assertNoEvents();
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006441 secondWindow->assertNoEvents();
6442 secondMonitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00006443}
6444
6445/**
6446 * One display with transform
6447 * There is a foreground window and a monitor on the display
6448 * Inject down event and move event sequentially, the foreground window and monitor can receive down
6449 * event and move event, then let the foreground window go away, the foreground window receives
6450 * cancel event, inject move event again, the monitor receives cancel event, all the events received
6451 * by the monitor should be with the same transform as the display
6452 */
6453TEST_F(InputDispatcherMonitorTest, MonitorTouchCancelEventWithDisplayTransform) {
6454 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6455 sp<FakeWindowHandle> window =
6456 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6457 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6458
6459 ui::Transform transform;
6460 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6461
6462 gui::DisplayInfo displayInfo;
6463 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6464 displayInfo.transform = transform;
6465
6466 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
6467
6468 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6469 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6470 {100, 200}))
6471 << "The down event injected should succeed";
6472
6473 window->consumeMotionDown();
6474 std::unique_ptr<MotionEvent> downMotionEvent = monitor.consumeMotion();
6475 EXPECT_EQ(transform, downMotionEvent->getTransform());
6476 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, downMotionEvent->getAction());
6477
6478 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6479 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6480 ADISPLAY_ID_DEFAULT, {110, 220}))
6481 << "The move event injected should succeed";
6482
6483 window->consumeMotionMove();
6484 std::unique_ptr<MotionEvent> moveMotionEvent = monitor.consumeMotion();
6485 EXPECT_EQ(transform, moveMotionEvent->getTransform());
6486 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, moveMotionEvent->getAction());
6487
6488 // Let foreground window gone
6489 mDispatcher->onWindowInfosChanged({{}, {displayInfo}, 0, 0});
6490
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006491 // Foreground window should receive a cancel event, but not the monitor.
Linnan Lid8150952024-01-26 18:07:17 +00006492 window->consumeMotionCancel();
Linnan Lid8150952024-01-26 18:07:17 +00006493
6494 ASSERT_EQ(InputEventInjectionResult::FAILED,
6495 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6496 ADISPLAY_ID_DEFAULT, {110, 220}))
6497 << "The move event injected should failed";
6498 // Now foreground should not receive any events, but monitor should receive a cancel event
6499 // with transform that same as display's display.
Linnan Lid8150952024-01-26 18:07:17 +00006500 std::unique_ptr<MotionEvent> cancelMotionEvent = monitor.consumeMotion();
6501 EXPECT_EQ(transform, cancelMotionEvent->getTransform());
6502 EXPECT_EQ(ADISPLAY_ID_DEFAULT, cancelMotionEvent->getDisplayId());
6503 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, cancelMotionEvent->getAction());
6504
6505 // Other event inject to this display should fail.
6506 ASSERT_EQ(InputEventInjectionResult::FAILED,
6507 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6508 ADISPLAY_ID_DEFAULT, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006509 << "The up event injected should fail because the touched window was removed";
Linnan Lid8150952024-01-26 18:07:17 +00006510 window->assertNoEvents();
6511 monitor.assertNoEvents();
6512}
6513
chaviw81e2bb92019-12-18 15:03:51 -08006514TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006515 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006516 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6517 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08006518
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006519 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08006520
6521 NotifyMotionArgs motionArgs =
6522 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6523 ADISPLAY_ID_DEFAULT);
6524
Prabir Pradhan678438e2023-04-13 19:32:51 +00006525 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08006526 // Window should receive motion down event.
6527 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6528
6529 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08006530 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08006531 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6532 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
6533 motionArgs.pointerCoords[0].getX() - 10);
6534
Prabir Pradhan678438e2023-04-13 19:32:51 +00006535 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006536 window->consumeMotionMove(ADISPLAY_ID_DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08006537}
6538
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006539/**
6540 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
6541 * the device default right away. In the test scenario, we check both the default value,
6542 * and the action of enabling / disabling.
6543 */
6544TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07006545 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006546 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6547 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08006548 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006549
6550 // Set focused application.
6551 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006552 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006553
6554 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006555 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006556 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006557 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006558
6559 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006560 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006561 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006562 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006563
6564 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006565 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006566 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006567 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07006568 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006569 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006570 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006571 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006572
6573 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006574 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006575 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006576 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006577
6578 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006579 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006580 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006581 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07006582 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006583 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006584 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006585 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006586
6587 window->assertNoEvents();
6588}
6589
Gang Wange9087892020-01-07 12:17:14 -05006590TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006591 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006592 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6593 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05006594
6595 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006596 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05006597
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006598 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006599 setFocusedWindow(window);
6600
Harry Cutts33476232023-01-30 19:57:29 +00006601 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05006602
Prabir Pradhan678438e2023-04-13 19:32:51 +00006603 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
6604 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05006605
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006606 std::unique_ptr<KeyEvent> event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05006607 ASSERT_NE(event, nullptr);
Gang Wange9087892020-01-07 12:17:14 -05006608 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
6609 ASSERT_NE(verified, nullptr);
6610 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
6611
6612 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
6613 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
6614 ASSERT_EQ(keyArgs.source, verified->source);
6615 ASSERT_EQ(keyArgs.displayId, verified->displayId);
6616
6617 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
6618
6619 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05006620 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006621 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05006622 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
6623 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
6624 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
6625 ASSERT_EQ(0, verifiedKey.repeatCount);
6626}
6627
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006628TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006629 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006630 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6631 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006632
6633 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6634
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006635 ui::Transform transform;
6636 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6637
6638 gui::DisplayInfo displayInfo;
6639 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6640 displayInfo.transform = transform;
6641
Patrick Williamsd828f302023-04-28 17:52:08 -05006642 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006643
Prabir Pradhan678438e2023-04-13 19:32:51 +00006644 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006645 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6646 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006647 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006648
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006649 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
6650 ASSERT_NE(nullptr, event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006651 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
6652 ASSERT_NE(verified, nullptr);
6653 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
6654
6655 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
6656 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
6657 EXPECT_EQ(motionArgs.source, verified->source);
6658 EXPECT_EQ(motionArgs.displayId, verified->displayId);
6659
6660 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
6661
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006662 const vec2 rawXY =
6663 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
6664 motionArgs.pointerCoords[0].getXYValue());
6665 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
6666 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006667 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006668 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006669 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006670 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
6671 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
6672}
6673
chaviw09c8d2d2020-08-24 15:48:26 -07006674/**
6675 * Ensure that separate calls to sign the same data are generating the same key.
6676 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
6677 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
6678 * tests.
6679 */
6680TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
6681 KeyEvent event = getTestKeyEvent();
6682 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6683
6684 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
6685 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
6686 ASSERT_EQ(hmac1, hmac2);
6687}
6688
6689/**
6690 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6691 */
6692TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6693 KeyEvent event = getTestKeyEvent();
6694 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6695 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6696
6697 verifiedEvent.deviceId += 1;
6698 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6699
6700 verifiedEvent.source += 1;
6701 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6702
6703 verifiedEvent.eventTimeNanos += 1;
6704 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6705
6706 verifiedEvent.displayId += 1;
6707 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6708
6709 verifiedEvent.action += 1;
6710 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6711
6712 verifiedEvent.downTimeNanos += 1;
6713 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6714
6715 verifiedEvent.flags += 1;
6716 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6717
6718 verifiedEvent.keyCode += 1;
6719 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6720
6721 verifiedEvent.scanCode += 1;
6722 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6723
6724 verifiedEvent.metaState += 1;
6725 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6726
6727 verifiedEvent.repeatCount += 1;
6728 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6729}
6730
Vishnu Nair958da932020-08-21 17:12:37 -07006731TEST_F(InputDispatcherTest, SetFocusedWindow) {
6732 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6733 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006734 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006735 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006736 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006737 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6738
6739 // Top window is also focusable but is not granted focus.
6740 windowTop->setFocusable(true);
6741 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006742 mDispatcher->onWindowInfosChanged(
6743 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006744 setFocusedWindow(windowSecond);
6745
6746 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006747 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006748 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006749
6750 // Focused window should receive event.
6751 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6752 windowTop->assertNoEvents();
6753}
6754
6755TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
6756 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6757 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006758 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006759 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6760
6761 window->setFocusable(true);
6762 // Release channel for window is no longer valid.
6763 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006764 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006765 setFocusedWindow(window);
6766
6767 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006768 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006769
6770 // window channel is invalid, so it should not receive any input event.
6771 window->assertNoEvents();
6772}
6773
6774TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
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, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006778 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006779 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6780
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006781 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006782 setFocusedWindow(window);
6783
6784 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006785 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006786
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006787 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006788 window->assertNoEvents();
6789}
6790
6791TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6792 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6793 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006794 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006795 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006796 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006797 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6798
6799 windowTop->setFocusable(true);
6800 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006801 mDispatcher->onWindowInfosChanged(
6802 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006803 setFocusedWindow(windowTop);
6804 windowTop->consumeFocusEvent(true);
6805
Chavi Weingarten847e8512023-03-29 00:26:09 +00006806 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006807 mDispatcher->onWindowInfosChanged(
6808 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006809 windowSecond->consumeFocusEvent(true);
6810 windowTop->consumeFocusEvent(false);
6811
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006812 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006813 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006814
6815 // Focused window should receive event.
6816 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6817}
6818
Chavi Weingarten847e8512023-03-29 00:26:09 +00006819TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006820 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6821 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006822 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006823 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006824 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006825 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6826
6827 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006828 windowSecond->setFocusable(false);
6829 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006830 mDispatcher->onWindowInfosChanged(
6831 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006832 setFocusedWindow(windowTop);
6833 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006834
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006835 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006836 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006837
6838 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006839 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006840 windowSecond->assertNoEvents();
6841}
6842
6843TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6844 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6845 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006846 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006847 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006848 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6849 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006850 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6851
6852 window->setFocusable(true);
6853 previousFocusedWindow->setFocusable(true);
6854 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006855 mDispatcher->onWindowInfosChanged(
6856 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006857 setFocusedWindow(previousFocusedWindow);
6858 previousFocusedWindow->consumeFocusEvent(true);
6859
6860 // Requesting focus on invisible window takes focus from currently focused window.
6861 setFocusedWindow(window);
6862 previousFocusedWindow->consumeFocusEvent(false);
6863
6864 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006865 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006866 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6867 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006868
6869 // Window does not get focus event or key down.
6870 window->assertNoEvents();
6871
6872 // Window becomes visible.
6873 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006874 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006875
6876 // Window receives focus event.
6877 window->consumeFocusEvent(true);
6878 // Focused window receives key down.
6879 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6880}
6881
Vishnu Nair599f1412021-06-21 10:39:58 -07006882TEST_F(InputDispatcherTest, DisplayRemoved) {
6883 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6884 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006885 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006886 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6887
6888 // window is granted focus.
6889 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006890 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006891 setFocusedWindow(window);
6892 window->consumeFocusEvent(true);
6893
6894 // When a display is removed window loses focus.
6895 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6896 window->consumeFocusEvent(false);
6897}
6898
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006899/**
6900 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6901 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6902 * of the 'slipperyEnterWindow'.
6903 *
6904 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6905 * a way so that the touched location is no longer covered by the top window.
6906 *
6907 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6908 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6909 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6910 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6911 * with ACTION_DOWN).
6912 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6913 * window moved itself away from the touched location and had Flag::SLIPPERY.
6914 *
6915 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6916 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6917 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6918 *
6919 * In this test, we ensure that the event received by the bottom window has
6920 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6921 */
6922TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006923 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006924 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006925
6926 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6927 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6928
6929 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006930 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006931 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006932 // Make sure this one overlaps the bottom window
6933 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6934 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6935 // one. Windows with the same owner are not considered to be occluding each other.
6936 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6937
6938 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006939 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006940 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6941
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006942 mDispatcher->onWindowInfosChanged(
6943 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006944
6945 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006946 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6947 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6948 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006949 slipperyExitWindow->consumeMotionDown();
6950 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006951 mDispatcher->onWindowInfosChanged(
6952 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006953
Prabir Pradhan678438e2023-04-13 19:32:51 +00006954 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6955 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6956 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006957
6958 slipperyExitWindow->consumeMotionCancel();
6959
6960 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6961 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6962}
6963
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006964/**
6965 * Two windows, one on the left and another on the right. The left window is slippery. The right
6966 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6967 * touch moves from the left window into the right window, the gesture should continue to go to the
6968 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6969 * reproduces a crash.
6970 */
6971TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6972 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6973
6974 sp<FakeWindowHandle> leftSlipperyWindow =
6975 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6976 leftSlipperyWindow->setSlippery(true);
6977 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6978
6979 sp<FakeWindowHandle> rightDropTouchesWindow =
6980 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6981 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6982 rightDropTouchesWindow->setDropInput(true);
6983
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006984 mDispatcher->onWindowInfosChanged(
6985 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006986
6987 // Start touch in the left window
6988 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6989 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6990 .build());
6991 leftSlipperyWindow->consumeMotionDown();
6992
6993 // And move it into the right window
6994 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6995 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6996 .build());
6997
6998 // Since the right window isn't eligible to receive input, touch does not slip.
6999 // The left window continues to receive the gesture.
7000 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
7001 rightDropTouchesWindow->assertNoEvents();
7002}
7003
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007004/**
7005 * A single window is on screen first. Touch is injected into that window. Next, a second window
7006 * appears. Since the first window is slippery, touch will move from the first window to the second.
7007 */
7008TEST_F(InputDispatcherTest, InjectedTouchSlips) {
7009 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7010 sp<FakeWindowHandle> originalWindow =
7011 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
7012 originalWindow->setFrame(Rect(0, 0, 200, 200));
7013 originalWindow->setSlippery(true);
7014
7015 sp<FakeWindowHandle> appearingWindow =
7016 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
7017 appearingWindow->setFrame(Rect(0, 0, 200, 200));
7018
7019 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
7020
7021 // Touch down on the original window
7022 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7023 injectMotionEvent(*mDispatcher,
7024 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7025 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
7026 .build()));
7027 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7028
7029 // Now, a new window appears. This could be, for example, a notification shade that appears
7030 // after user starts to drag down on the launcher window.
7031 mDispatcher->onWindowInfosChanged(
7032 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
7033 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7034 injectMotionEvent(*mDispatcher,
7035 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7036 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
7037 .build()));
7038 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7039 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7040 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7041 injectMotionEvent(*mDispatcher,
7042 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7043 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
7044 .build()));
7045 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
7046
7047 originalWindow->assertNoEvents();
7048 appearingWindow->assertNoEvents();
7049}
7050
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007051TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007052 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007053 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7054
7055 sp<FakeWindowHandle> leftWindow =
7056 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
7057 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007058 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007059
7060 sp<FakeWindowHandle> rightSpy =
7061 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
7062 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007063 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007064 rightSpy->setSpy(true);
7065 rightSpy->setTrustedOverlay(true);
7066
7067 sp<FakeWindowHandle> rightWindow =
7068 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
7069 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007070 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007071
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007072 mDispatcher->onWindowInfosChanged(
7073 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007074
7075 // Touch in the left window
7076 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7077 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7078 .build());
7079 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
7080 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007081 ASSERT_NO_FATAL_FAILURE(
7082 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007083
7084 // Touch another finger over the right windows
7085 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7086 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7087 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7088 .build());
7089 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
7090 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
7091 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
7092 mDispatcher->waitForIdle();
7093 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007094 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
7095 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007096
7097 // Release finger over left window. The UP actions are not treated as device interaction.
7098 // The windows that did not receive the UP pointer will receive MOVE events, but since this
7099 // is part of the UP action, we do not treat this as device interaction.
7100 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
7101 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7102 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7103 .build());
7104 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
7105 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
7106 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
7107 mDispatcher->waitForIdle();
7108 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7109
7110 // Move remaining finger
7111 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7112 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7113 .build());
7114 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
7115 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
7116 mDispatcher->waitForIdle();
7117 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007118 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007119
7120 // Release all fingers
7121 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7122 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7123 .build());
7124 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
7125 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
7126 mDispatcher->waitForIdle();
7127 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7128}
7129
7130TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
7131 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7132
7133 sp<FakeWindowHandle> window =
7134 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
7135 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007136 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007137
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007138 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007139 setFocusedWindow(window);
7140 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
7141
7142 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
7143 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
7144 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007145 ASSERT_NO_FATAL_FAILURE(
7146 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007147
7148 // The UP actions are not treated as device interaction.
7149 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
7150 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
7151 mDispatcher->waitForIdle();
7152 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7153}
7154
Prabir Pradhan5893d362023-11-17 04:30:40 +00007155TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
7156 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7157
7158 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
7159 ADISPLAY_ID_DEFAULT);
7160 left->setFrame(Rect(0, 0, 100, 100));
7161 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
7162 "Right Window", ADISPLAY_ID_DEFAULT);
7163 right->setFrame(Rect(100, 0, 200, 100));
7164 sp<FakeWindowHandle> spy =
7165 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
7166 spy->setFrame(Rect(0, 0, 200, 100));
7167 spy->setTrustedOverlay(true);
7168 spy->setSpy(true);
7169
7170 mDispatcher->onWindowInfosChanged(
7171 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
7172
7173 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
7174 NotifyMotionArgs notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
7175 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
7176 mDispatcher->notifyMotion(notifyArgs);
7177
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007178 std::unique_ptr<MotionEvent> leftEnter = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00007179 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
7180 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007181 ASSERT_NE(nullptr, leftEnter);
Prabir Pradhan5893d362023-11-17 04:30:40 +00007182 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
7183 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007184 Not(WithEventId(leftEnter->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00007185 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
7186
7187 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
7188 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
7189 {PointF{150, 50}});
7190 mDispatcher->notifyMotion(notifyArgs);
7191
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007192 std::unique_ptr<MotionEvent> leftExit = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00007193 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
7194 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007195 ASSERT_NE(nullptr, leftExit);
Prabir Pradhan5893d362023-11-17 04:30:40 +00007196 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
7197 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007198 Not(WithEventId(leftExit->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00007199 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
7200
7201 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
7202}
7203
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00007204class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
7205protected:
7206 std::shared_ptr<FakeApplicationHandle> mApp;
7207 sp<FakeWindowHandle> mWindow;
7208
7209 virtual void SetUp() override {
7210 InputDispatcherTest::SetUp();
7211
7212 mApp = std::make_shared<FakeApplicationHandle>();
7213
7214 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
7215 mWindow->setFrame(Rect(0, 0, 100, 100));
7216
7217 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
7218 setFocusedWindow(mWindow);
7219 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
7220 }
7221
7222 void setFallback(int32_t keycode) {
7223 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
7224 return KeyEventBuilder(event).keyCode(keycode).build();
7225 });
7226 }
7227
7228 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007229 std::unique_ptr<KeyEvent> event = mWindow->consumeKey(handled);
7230 ASSERT_NE(nullptr, event);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00007231 ASSERT_THAT(*event, matcher);
7232 }
7233};
7234
7235TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
7236 mDispatcher->notifyKey(
7237 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7238 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
7239 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7240}
7241
7242TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
7243 mDispatcher->notifyKey(
7244 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7245 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
7246 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7247}
7248
7249TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
7250 mDispatcher->notifyKey(
7251 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7252
7253 // Do not handle this key event.
7254 consumeKey(/*handled=*/false,
7255 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7256 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7257
7258 // Since the policy did not request any fallback to be generated, ensure there are no events.
7259 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7260}
7261
7262TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
7263 setFallback(AKEYCODE_B);
7264 mDispatcher->notifyKey(
7265 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7266
7267 // Do not handle this key event.
7268 consumeKey(/*handled=*/false,
7269 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7270
7271 // Since the key was not handled, ensure the fallback event was dispatched instead.
7272 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7273 consumeKey(/*handled=*/true,
7274 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7275 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7276
7277 // Release the original key, and ensure the fallback key is also released.
7278 mDispatcher->notifyKey(
7279 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7280 consumeKey(/*handled=*/false,
7281 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7282 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7283 consumeKey(/*handled=*/true,
7284 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7285 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7286
7287 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7288 mWindow->assertNoEvents();
7289}
7290
7291TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
7292 setFallback(AKEYCODE_B);
7293 mDispatcher->notifyKey(
7294 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7295
7296 // Do not handle this key event, but handle the fallback.
7297 consumeKey(/*handled=*/false,
7298 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7299 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7300 consumeKey(/*handled=*/true,
7301 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7302 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7303
7304 // Release the original key, and ensure the fallback key is also released.
7305 mDispatcher->notifyKey(
7306 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7307 // But this time, the app handles the original key.
7308 consumeKey(/*handled=*/true,
7309 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7310 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7311 // Ensure the fallback key is canceled.
7312 consumeKey(/*handled=*/true,
7313 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7314 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7315
7316 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7317 mWindow->assertNoEvents();
7318}
7319
7320TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
7321 setFallback(AKEYCODE_B);
7322 mDispatcher->notifyKey(
7323 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7324
7325 // Do not handle this key event.
7326 consumeKey(/*handled=*/false,
7327 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7328 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7329 // App does not handle the fallback either, so ensure another fallback is not generated.
7330 setFallback(AKEYCODE_C);
7331 consumeKey(/*handled=*/false,
7332 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7333 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7334
7335 // Release the original key, and ensure the fallback key is also released.
7336 setFallback(AKEYCODE_B);
7337 mDispatcher->notifyKey(
7338 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7339 consumeKey(/*handled=*/false,
7340 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7341 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7342 consumeKey(/*handled=*/false,
7343 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7344 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7345
7346 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7347 mWindow->assertNoEvents();
7348}
7349
7350TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
7351 setFallback(AKEYCODE_B);
7352 mDispatcher->notifyKey(
7353 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7354
7355 // Do not handle this key event, so fallback is generated.
7356 consumeKey(/*handled=*/false,
7357 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7358 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7359 consumeKey(/*handled=*/true,
7360 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7361 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7362
7363 // Release the original key, but assume the policy is misbehaving and it
7364 // generates an inconsistent fallback to the one from the DOWN event.
7365 setFallback(AKEYCODE_C);
7366 mDispatcher->notifyKey(
7367 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7368 consumeKey(/*handled=*/false,
7369 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7370 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7371 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
7372 consumeKey(/*handled=*/true,
7373 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7374 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7375
7376 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7377 mWindow->assertNoEvents();
7378}
7379
7380TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
7381 setFallback(AKEYCODE_B);
7382 mDispatcher->notifyKey(
7383 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7384
7385 // Do not handle this key event, so fallback is generated.
7386 consumeKey(/*handled=*/false,
7387 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7388 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7389 consumeKey(/*handled=*/true,
7390 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7391 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7392
7393 // The original key is canceled.
7394 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
7395 .keyCode(AKEYCODE_A)
7396 .addFlag(AKEY_EVENT_FLAG_CANCELED)
7397 .build());
7398 consumeKey(/*handled=*/false,
7399 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
7400 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7401 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7402 // Ensure the fallback key is also canceled due to the original key being canceled.
7403 consumeKey(/*handled=*/true,
7404 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7405 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7406
7407 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7408 mWindow->assertNoEvents();
7409}
7410
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00007411TEST_F(InputDispatcherFallbackKeyTest, InputChannelRemovedDuringPolicyCall) {
Prabir Pradhanb13da8f2024-01-09 23:10:13 +00007412 setFallback(AKEYCODE_B);
7413 mDispatcher->notifyKey(
7414 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7415
7416 // Do not handle this key event.
7417 consumeKey(/*handled=*/false,
7418 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7419 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7420 consumeKey(/*handled=*/true,
7421 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7422 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7423
7424 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
7425 // When the unhandled key is reported to the policy next, remove the input channel.
7426 mDispatcher->removeInputChannel(mWindow->getToken());
7427 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
7428 });
7429 // Release the original key, and let the app now handle the previously unhandled key.
7430 // This should result in the previously generated fallback key to be cancelled.
7431 // Since the policy was notified of the unhandled DOWN event earlier, it will also be notified
7432 // of the UP event for consistency. The Dispatcher calls into the policy from its own thread
7433 // without holding the lock, because it need to synchronously fetch the fallback key. While in
7434 // the policy call, we will now remove the input channel. Once the policy call returns, the
7435 // Dispatcher will no longer have a channel to send cancellation events to. Ensure this does
7436 // not cause any crashes.
7437 mDispatcher->notifyKey(
7438 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7439 consumeKey(/*handled=*/true,
7440 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7441 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7442}
7443
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00007444TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedDuringPolicyCall) {
7445 setFallback(AKEYCODE_B);
7446 mDispatcher->notifyKey(
7447 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7448
7449 // Do not handle this key event.
7450 consumeKey(/*handled=*/false,
7451 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7452 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7453 consumeKey(/*handled=*/true,
7454 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7455 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7456
7457 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
7458 // When the unhandled key is reported to the policy next, remove the window.
7459 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
7460 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
7461 });
7462 // Release the original key, which the app will not handle. When this unhandled key is reported
7463 // to the policy, the window will be removed.
7464 mDispatcher->notifyKey(
7465 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7466 consumeKey(/*handled=*/false,
7467 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7468 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7469
7470 // Since the window was removed, it loses focus, and the channel state will be reset.
7471 consumeKey(/*handled=*/true,
7472 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7473 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7474 mWindow->consumeFocusEvent(false);
7475 mWindow->assertNoEvents();
7476}
7477
7478TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedWhileAwaitingFinishedSignal) {
7479 setFallback(AKEYCODE_B);
7480 mDispatcher->notifyKey(
7481 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7482
7483 // Do not handle this key event.
7484 consumeKey(/*handled=*/false,
7485 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7486 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7487 const auto [seq, event] = mWindow->receiveEvent();
7488 ASSERT_TRUE(seq.has_value() && event != nullptr) << "Failed to receive fallback event";
7489 ASSERT_EQ(event->getType(), InputEventType::KEY);
7490 ASSERT_THAT(static_cast<const KeyEvent&>(*event),
7491 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7492 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7493
7494 // Remove the window now, which should generate a cancellations and make the window lose focus.
7495 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
7496 consumeKey(/*handled=*/true,
7497 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
7498 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7499 consumeKey(/*handled=*/true,
7500 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7501 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7502 mWindow->consumeFocusEvent(false);
7503
7504 // Finish the event by reporting it as handled.
7505 mWindow->finishEvent(*seq);
7506 mWindow->assertNoEvents();
7507}
7508
Garfield Tan1c7bc862020-01-28 13:24:04 -08007509class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
7510protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08007511 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
7512 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007513
Chris Yea209fde2020-07-22 13:54:51 -07007514 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007515 sp<FakeWindowHandle> mWindow;
7516
7517 virtual void SetUp() override {
Prabir Pradhandae52792023-12-15 07:36:40 +00007518 InputDispatcherTest::SetUp();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007519
Prabir Pradhandae52792023-12-15 07:36:40 +00007520 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007521 setUpWindow();
7522 }
7523
7524 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07007525 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007526 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007527
Vishnu Nair47074b82020-08-14 11:54:47 -07007528 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007529 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007530 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007531 mWindow->consumeFocusEvent(true);
7532 }
7533
Chris Ye2ad95392020-09-01 13:44:44 -07007534 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007535 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007536 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007537 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007538 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007539
7540 // Window should receive key down event.
7541 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7542 }
7543
7544 void expectKeyRepeatOnce(int32_t repeatCount) {
7545 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007546 mWindow->consumeKeyEvent(
7547 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007548 }
7549
Chris Ye2ad95392020-09-01 13:44:44 -07007550 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007551 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007552 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007553 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007554 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007555
7556 // Window should receive key down event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007557 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007558 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007559 }
7560};
7561
7562TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00007563 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007564 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7565 expectKeyRepeatOnce(repeatCount);
7566 }
7567}
7568
7569TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00007570 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007571 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7572 expectKeyRepeatOnce(repeatCount);
7573 }
Harry Cutts33476232023-01-30 19:57:29 +00007574 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007575 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08007576 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7577 expectKeyRepeatOnce(repeatCount);
7578 }
7579}
7580
7581TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007582 sendAndConsumeKeyDown(/*deviceId=*/1);
7583 expectKeyRepeatOnce(/*repeatCount=*/1);
7584 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007585 mWindow->assertNoEvents();
7586}
7587
7588TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007589 sendAndConsumeKeyDown(/*deviceId=*/1);
7590 expectKeyRepeatOnce(/*repeatCount=*/1);
7591 sendAndConsumeKeyDown(/*deviceId=*/2);
7592 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007593 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00007594 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007595 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00007596 expectKeyRepeatOnce(/*repeatCount=*/2);
7597 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07007598 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00007599 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007600 mWindow->assertNoEvents();
7601}
7602
7603TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007604 sendAndConsumeKeyDown(/*deviceId=*/1);
7605 expectKeyRepeatOnce(/*repeatCount=*/1);
7606 sendAndConsumeKeyDown(/*deviceId=*/2);
7607 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007608 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00007609 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007610 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08007611 mWindow->assertNoEvents();
7612}
7613
liushenxiang42232912021-05-21 20:24:09 +08007614TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
7615 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00007616 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007617 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08007618 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
7619 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
7620 mWindow->assertNoEvents();
7621}
7622
Garfield Tan1c7bc862020-01-28 13:24:04 -08007623TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007624 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007625 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007626 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007627 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
7628 ASSERT_NE(nullptr, repeatEvent);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007629 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
7630 IdGenerator::getSource(repeatEvent->getId()));
7631 }
7632}
7633
7634TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007635 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007636 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007637
7638 std::unordered_set<int32_t> idSet;
7639 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007640 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
7641 ASSERT_NE(nullptr, repeatEvent);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007642 int32_t id = repeatEvent->getId();
7643 EXPECT_EQ(idSet.end(), idSet.find(id));
7644 idSet.insert(id);
7645 }
7646}
7647
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007648/* Test InputDispatcher for MultiDisplay */
7649class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
7650public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007651 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007652 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08007653
Chris Yea209fde2020-07-22 13:54:51 -07007654 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007655 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007656 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007657
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007658 // Set focus window for primary display, but focused display would be second one.
7659 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07007660 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007661 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
7662
Vishnu Nair958da932020-08-21 17:12:37 -07007663 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007664 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08007665
Chris Yea209fde2020-07-22 13:54:51 -07007666 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007667 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007668 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007669 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007670 // Set focus display to second one.
7671 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
7672 // Set focus window for second display.
7673 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07007674 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007675 mDispatcher->onWindowInfosChanged(
7676 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007677 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007678 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007679 }
7680
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007681 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007682 InputDispatcherTest::TearDown();
7683
Chris Yea209fde2020-07-22 13:54:51 -07007684 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007685 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07007686 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007687 windowInSecondary.clear();
7688 }
7689
7690protected:
Chris Yea209fde2020-07-22 13:54:51 -07007691 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007692 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07007693 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007694 sp<FakeWindowHandle> windowInSecondary;
7695};
7696
7697TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
7698 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007699 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007700 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007701 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007702 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08007703 windowInSecondary->assertNoEvents();
7704
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007705 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007706 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007707 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007708 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007709 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007710 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08007711}
7712
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007713TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08007714 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007715 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007716 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007717 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007718 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08007719 windowInSecondary->assertNoEvents();
7720
7721 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007722 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007723 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007724 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007725 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08007726
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007727 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007728 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08007729
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007730 // Old focus should receive a cancel event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007731 windowInSecondary->consumeKeyUp(ADISPLAY_ID_NONE, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08007732
7733 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007734 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08007735 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007736 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08007737 windowInSecondary->assertNoEvents();
7738}
7739
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007740// Test per-display input monitors for motion event.
7741TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08007742 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007743 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007744 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007745 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007746
7747 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007748 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007749 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007750 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007751 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007752 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007753 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007754 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007755
7756 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007757 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007758 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007759 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007760 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007761 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007762 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08007763 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007764
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007765 // Lift up the touch from the second display
7766 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007767 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007768 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7769 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
7770 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
7771
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007772 // Test inject a non-pointer motion event.
7773 // If specific a display, it will dispatch to the focused window of particular display,
7774 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007775 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007776 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007777 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007778 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007779 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007780 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007781 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007782}
7783
7784// Test per-display input monitors for key event.
7785TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007786 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08007787 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007788 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007789 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007790 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007791
7792 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007793 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007794 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007795 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007796 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007797 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007798 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007799}
7800
Vishnu Nair958da932020-08-21 17:12:37 -07007801TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
7802 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007803 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007804 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007805 mDispatcher->onWindowInfosChanged(
7806 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
7807 *windowInSecondary->getInfo()},
7808 {},
7809 0,
7810 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007811 setFocusedWindow(secondWindowInPrimary);
7812 windowInPrimary->consumeFocusEvent(false);
7813 secondWindowInPrimary->consumeFocusEvent(true);
7814
7815 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007816 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7817 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007818 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007819 windowInPrimary->assertNoEvents();
7820 windowInSecondary->assertNoEvents();
7821 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7822}
7823
Arthur Hungdfd528e2021-12-08 13:23:04 +00007824TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
7825 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007826 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007827 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007828 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007829
7830 // Test touch down on primary display.
7831 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007832 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007833 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7834 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7835 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
7836
7837 // Test touch down on second display.
7838 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007839 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007840 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7841 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
7842 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
7843
7844 // Trigger cancel touch.
7845 mDispatcher->cancelCurrentTouch();
7846 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7847 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7848 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
7849 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
7850
7851 // Test inject a move motion event, no window/monitor should receive the event.
7852 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007853 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007854 ADISPLAY_ID_DEFAULT, {110, 200}))
7855 << "Inject motion event should return InputEventInjectionResult::FAILED";
7856 windowInPrimary->assertNoEvents();
7857 monitorInPrimary.assertNoEvents();
7858
7859 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007860 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007861 SECOND_DISPLAY_ID, {110, 200}))
7862 << "Inject motion event should return InputEventInjectionResult::FAILED";
7863 windowInSecondary->assertNoEvents();
7864 monitorInSecondary.assertNoEvents();
7865}
7866
Hu Guocb134f12023-12-23 13:42:44 +00007867/**
7868 * Send a key to the primary display and to the secondary display.
7869 * Then cause the key on the primary display to be canceled by sending in a stale key.
7870 * Ensure that the key on the primary display is canceled, and that the key on the secondary display
7871 * does not get canceled.
7872 */
7873TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture) {
7874 // Send a key down on primary display
7875 mDispatcher->notifyKey(
7876 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7877 .displayId(ADISPLAY_ID_DEFAULT)
7878 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7879 .build());
7880 windowInPrimary->consumeKeyEvent(
7881 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7882 windowInSecondary->assertNoEvents();
7883
7884 // Send a key down on second display
7885 mDispatcher->notifyKey(
7886 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7887 .displayId(SECOND_DISPLAY_ID)
7888 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7889 .build());
7890 windowInSecondary->consumeKeyEvent(
7891 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7892 windowInPrimary->assertNoEvents();
7893
7894 // Send a valid key up event on primary display that will be dropped because it is stale
7895 NotifyKeyArgs staleKeyUp =
7896 KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
7897 .displayId(ADISPLAY_ID_DEFAULT)
7898 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7899 .build();
7900 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7901 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7902 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7903 mDispatcher->notifyKey(staleKeyUp);
7904
7905 // Only the key gesture corresponding to the dropped event should receive the cancel event.
7906 // Therefore, windowInPrimary should get the cancel event and windowInSecondary should not
7907 // receive any events.
7908 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
7909 WithDisplayId(ADISPLAY_ID_DEFAULT),
7910 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7911 windowInSecondary->assertNoEvents();
7912}
7913
7914/**
7915 * Similar to 'WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture' but for motion events.
7916 */
7917TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropMotionEvent_OnlyCancelCorrespondingGesture) {
7918 // Send touch down on primary display.
7919 mDispatcher->notifyMotion(
7920 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7921 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7922 .displayId(ADISPLAY_ID_DEFAULT)
7923 .build());
7924 windowInPrimary->consumeMotionEvent(
7925 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7926 windowInSecondary->assertNoEvents();
7927
7928 // Send touch down on second display.
7929 mDispatcher->notifyMotion(
7930 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7931 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7932 .displayId(SECOND_DISPLAY_ID)
7933 .build());
7934 windowInPrimary->assertNoEvents();
7935 windowInSecondary->consumeMotionEvent(
7936 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7937
7938 // inject a valid MotionEvent on primary display that will be stale when it arrives.
7939 NotifyMotionArgs staleMotionUp =
7940 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7941 .displayId(ADISPLAY_ID_DEFAULT)
7942 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7943 .build();
7944 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7945 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7946 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7947 mDispatcher->notifyMotion(staleMotionUp);
7948
7949 // For stale motion events, we let the gesture to complete. This behaviour is different from key
7950 // events, where we would cancel the current keys instead.
7951 windowInPrimary->consumeMotionEvent(WithMotionAction(ACTION_UP));
7952 windowInSecondary->assertNoEvents();
7953}
7954
Jackal Guof9696682018-10-05 12:23:23 +08007955class InputFilterTest : public InputDispatcherTest {
7956protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007957 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
7958 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08007959 NotifyMotionArgs motionArgs;
7960
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007961 motionArgs =
7962 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007963 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007964 motionArgs =
7965 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007966 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007967 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007968 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007969 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007970 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08007971 } else {
7972 mFakePolicy->assertFilterInputEventWasNotCalled();
7973 }
7974 }
7975
7976 void testNotifyKey(bool expectToBeFiltered) {
7977 NotifyKeyArgs keyArgs;
7978
7979 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007980 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007981 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007982 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007983 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007984
7985 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08007986 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007987 } else {
7988 mFakePolicy->assertFilterInputEventWasNotCalled();
7989 }
7990 }
7991};
7992
7993// Test InputFilter for MotionEvent
7994TEST_F(InputFilterTest, MotionEvent_InputFilter) {
7995 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007996 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7997 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007998
7999 // Enable InputFilter
8000 mDispatcher->setInputFilterEnabled(true);
8001 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00008002 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
8003 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08008004
8005 // Disable InputFilter
8006 mDispatcher->setInputFilterEnabled(false);
8007 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00008008 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
8009 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08008010}
8011
8012// Test InputFilter for KeyEvent
8013TEST_F(InputFilterTest, KeyEvent_InputFilter) {
8014 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00008015 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08008016
8017 // Enable InputFilter
8018 mDispatcher->setInputFilterEnabled(true);
8019 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00008020 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08008021
8022 // Disable InputFilter
8023 mDispatcher->setInputFilterEnabled(false);
8024 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00008025 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08008026}
8027
Prabir Pradhan81420cc2021-09-06 10:28:50 -07008028// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
8029// logical display coordinate space.
8030TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
8031 ui::Transform firstDisplayTransform;
8032 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
8033 ui::Transform secondDisplayTransform;
8034 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
8035
8036 std::vector<gui::DisplayInfo> displayInfos(2);
8037 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
8038 displayInfos[0].transform = firstDisplayTransform;
8039 displayInfos[1].displayId = SECOND_DISPLAY_ID;
8040 displayInfos[1].transform = secondDisplayTransform;
8041
Patrick Williamsd828f302023-04-28 17:52:08 -05008042 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07008043
8044 // Enable InputFilter
8045 mDispatcher->setInputFilterEnabled(true);
8046
8047 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00008048 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
8049 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07008050}
8051
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008052class InputFilterInjectionPolicyTest : public InputDispatcherTest {
8053protected:
8054 virtual void SetUp() override {
8055 InputDispatcherTest::SetUp();
8056
8057 /**
8058 * We don't need to enable input filter to test the injected event policy, but we enabled it
8059 * here to make the tests more realistic, since this policy only matters when inputfilter is
8060 * on.
8061 */
8062 mDispatcher->setInputFilterEnabled(true);
8063
8064 std::shared_ptr<InputApplicationHandle> application =
8065 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008066 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
8067 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008068
8069 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8070 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008071 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008072 setFocusedWindow(mWindow);
8073 mWindow->consumeFocusEvent(true);
8074 }
8075
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008076 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
8077 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008078 KeyEvent event;
8079
8080 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
8081 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
8082 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00008083 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008084 const int32_t additionalPolicyFlags =
8085 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
8086 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00008087 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00008088 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008089 policyFlags | additionalPolicyFlags));
8090
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008091 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008092 }
8093
8094 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
8095 int32_t flags) {
8096 MotionEvent event;
8097 PointerProperties pointerProperties[1];
8098 PointerCoords pointerCoords[1];
8099 pointerProperties[0].clear();
8100 pointerProperties[0].id = 0;
8101 pointerCoords[0].clear();
8102 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
8103 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
8104
8105 ui::Transform identityTransform;
8106 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
8107 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
8108 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
8109 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
8110 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07008111 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07008112 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00008113 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008114
8115 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
8116 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00008117 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00008118 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008119 policyFlags | additionalPolicyFlags));
8120
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008121 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008122 }
8123
8124private:
8125 sp<FakeWindowHandle> mWindow;
8126};
8127
8128TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008129 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
8130 // filter. Without it, the event will no different from a regularly injected event, and the
8131 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00008132 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
8133 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008134}
8135
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008136TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008137 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00008138 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008139 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
8140}
8141
8142TEST_F(InputFilterInjectionPolicyTest,
8143 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
8144 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00008145 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008146 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008147}
8148
8149TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00008150 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
8151 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008152}
8153
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08008154class InputDispatcherUserActivityPokeTests : public InputDispatcherTest {
8155protected:
8156 virtual void SetUp() override {
8157 InputDispatcherTest::SetUp();
8158
8159 std::shared_ptr<FakeApplicationHandle> application =
8160 std::make_shared<FakeApplicationHandle>();
8161 application->setDispatchingTimeout(100ms);
8162 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
8163 ADISPLAY_ID_DEFAULT);
Yeabkal Wubshit222d83d2024-01-24 18:00:09 +00008164 mWindow->setFrame(Rect(0, 0, 100, 100));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08008165 mWindow->setDispatchingTimeout(100ms);
8166 mWindow->setFocusable(true);
8167
8168 // Set focused application.
8169 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8170
8171 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
8172 setFocusedWindow(mWindow);
8173 mWindow->consumeFocusEvent(true);
8174 }
8175
8176 void notifyAndConsumeMotion(int32_t action, uint32_t source, int32_t displayId,
8177 nsecs_t eventTime) {
8178 mDispatcher->notifyMotion(MotionArgsBuilder(action, source)
8179 .displayId(displayId)
8180 .eventTime(eventTime)
8181 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8182 .build());
8183 mWindow->consumeMotionEvent(WithMotionAction(action));
8184 }
8185
8186private:
8187 sp<FakeWindowHandle> mWindow;
8188};
8189
8190TEST_F_WITH_FLAGS(
8191 InputDispatcherUserActivityPokeTests, MinPokeTimeObserved,
8192 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8193 rate_limit_user_activity_poke_in_dispatcher))) {
8194 mDispatcher->setMinTimeBetweenUserActivityPokes(50ms);
8195
8196 // First event of type TOUCH. Should poke.
8197 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8198 milliseconds_to_nanoseconds(50));
8199 mFakePolicy->assertUserActivityPoked(
8200 {{milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8201
8202 // 80ns > 50ns has passed since previous TOUCH event. Should poke.
8203 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8204 milliseconds_to_nanoseconds(130));
8205 mFakePolicy->assertUserActivityPoked(
8206 {{milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8207
8208 // First event of type OTHER. Should poke (despite being within 50ns of previous TOUCH event).
8209 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8210 milliseconds_to_nanoseconds(135));
8211 mFakePolicy->assertUserActivityPoked(
8212 {{milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER, ADISPLAY_ID_DEFAULT}});
8213
8214 // Within 50ns of previous TOUCH event. Should NOT poke.
8215 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8216 milliseconds_to_nanoseconds(140));
8217 mFakePolicy->assertUserActivityNotPoked();
8218
8219 // Within 50ns of previous OTHER event. Should NOT poke.
8220 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8221 milliseconds_to_nanoseconds(150));
8222 mFakePolicy->assertUserActivityNotPoked();
8223
8224 // Within 50ns of previous TOUCH event (which was at time 130). Should NOT poke.
8225 // Note that STYLUS is mapped to TOUCH user activity, since it's a pointer-type source.
8226 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
8227 milliseconds_to_nanoseconds(160));
8228 mFakePolicy->assertUserActivityNotPoked();
8229
8230 // 65ns > 50ns has passed since previous OTHER event. Should poke.
8231 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8232 milliseconds_to_nanoseconds(200));
8233 mFakePolicy->assertUserActivityPoked(
8234 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER, ADISPLAY_ID_DEFAULT}});
8235
8236 // 170ns > 50ns has passed since previous TOUCH event. Should poke.
8237 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
8238 milliseconds_to_nanoseconds(300));
8239 mFakePolicy->assertUserActivityPoked(
8240 {{milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8241
8242 // Assert that there's no more user activity poke event.
8243 mFakePolicy->assertUserActivityNotPoked();
8244}
8245
8246TEST_F_WITH_FLAGS(
8247 InputDispatcherUserActivityPokeTests, DefaultMinPokeTimeOf100MsUsed,
8248 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8249 rate_limit_user_activity_poke_in_dispatcher))) {
8250 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8251 milliseconds_to_nanoseconds(200));
8252 mFakePolicy->assertUserActivityPoked(
8253 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8254
8255 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8256 milliseconds_to_nanoseconds(280));
8257 mFakePolicy->assertUserActivityNotPoked();
8258
8259 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8260 milliseconds_to_nanoseconds(340));
8261 mFakePolicy->assertUserActivityPoked(
8262 {{milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8263}
8264
8265TEST_F_WITH_FLAGS(
8266 InputDispatcherUserActivityPokeTests, ZeroMinPokeTimeDisablesRateLimiting,
8267 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8268 rate_limit_user_activity_poke_in_dispatcher))) {
8269 mDispatcher->setMinTimeBetweenUserActivityPokes(0ms);
8270
8271 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20);
8272 mFakePolicy->assertUserActivityPoked();
8273
8274 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 30);
8275 mFakePolicy->assertUserActivityPoked();
8276}
8277
chaviwfd6d3512019-03-25 13:23:49 -07008278class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008279 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07008280 InputDispatcherTest::SetUp();
8281
Chris Yea209fde2020-07-22 13:54:51 -07008282 std::shared_ptr<FakeApplicationHandle> application =
8283 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008284 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008285 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07008286 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07008287
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008288 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008289 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008290 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07008291
8292 // Set focused application.
8293 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07008294 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07008295
8296 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008297 mDispatcher->onWindowInfosChanged(
8298 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008299 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008300 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07008301 }
8302
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008303 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07008304 InputDispatcherTest::TearDown();
8305
8306 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008307 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07008308 }
8309
8310protected:
8311 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008312 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008313 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07008314};
8315
8316// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
8317// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
8318// the onPointerDownOutsideFocus callback.
8319TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008320 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008321 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008322 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008323 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008324 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008325
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008326 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07008327 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
8328}
8329
8330// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
8331// DOWN on the window that doesn't have focus. Ensure no window received the
8332// onPointerDownOutsideFocus callback.
8333TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008334 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008335 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
8336 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008337 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008338 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008339
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008340 ASSERT_TRUE(mDispatcher->waitForIdle());
8341 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008342}
8343
8344// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
8345// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
8346TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08008347 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008348 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008349 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008350 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07008351
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008352 ASSERT_TRUE(mDispatcher->waitForIdle());
8353 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008354}
8355
8356// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
8357// DOWN on the window that already has focus. Ensure no window received the
8358// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008359TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008360 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008361 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008362 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008363 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008364 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008365
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008366 ASSERT_TRUE(mDispatcher->waitForIdle());
8367 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008368}
8369
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008370// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
8371// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
8372TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
8373 const MotionEvent event =
8374 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
8375 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008376 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008377 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
8378 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008379 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008380 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8381 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
8382
8383 ASSERT_TRUE(mDispatcher->waitForIdle());
8384 mFakePolicy->assertOnPointerDownWasNotCalled();
8385 // Ensure that the unfocused window did not receive any FOCUS events.
8386 mUnfocusedWindow->assertNoEvents();
8387}
8388
chaviwaf87b3e2019-10-01 16:59:28 -07008389// These tests ensures we can send touch events to a single client when there are multiple input
8390// windows that point to the same client token.
8391class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
8392 virtual void SetUp() override {
8393 InputDispatcherTest::SetUp();
8394
Chris Yea209fde2020-07-22 13:54:51 -07008395 std::shared_ptr<FakeApplicationHandle> application =
8396 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008397 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
8398 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07008399 mWindow1->setFrame(Rect(0, 0, 100, 100));
8400
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00008401 mWindow2 = mWindow1->clone(ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07008402 mWindow2->setFrame(Rect(100, 100, 200, 200));
8403
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008404 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07008405 }
8406
8407protected:
8408 sp<FakeWindowHandle> mWindow1;
8409 sp<FakeWindowHandle> mWindow2;
8410
8411 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05008412 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07008413 vec2 vals = windowInfo->transform.transform(point.x, point.y);
8414 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07008415 }
8416
8417 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
8418 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008419 const std::string name = window->getName();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008420 std::unique_ptr<MotionEvent> motionEvent =
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008421 window->consumeMotionEvent(WithMotionAction(expectedAction));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008422 ASSERT_NE(nullptr, motionEvent);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008423 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07008424
8425 for (size_t i = 0; i < points.size(); i++) {
8426 float expectedX = points[i].x;
8427 float expectedY = points[i].y;
8428
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008429 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07008430 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008431 << ", got " << motionEvent->getX(i);
8432 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07008433 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008434 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07008435 }
8436 }
chaviw9eaa22c2020-07-01 16:21:27 -07008437
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008438 void touchAndAssertPositions(sp<FakeWindowHandle> touchedWindow, int32_t action,
8439 const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07008440 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008441 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
8442 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07008443
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008444 consumeMotionEvent(touchedWindow, action, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008445 }
chaviwaf87b3e2019-10-01 16:59:28 -07008446};
8447
8448TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
8449 // Touch Window 1
8450 PointF touchedPoint = {10, 10};
8451 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008452 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008453
8454 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008455 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008456
8457 // Touch Window 2
8458 touchedPoint = {150, 150};
8459 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008460 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008461}
8462
chaviw9eaa22c2020-07-01 16:21:27 -07008463TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
8464 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07008465 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008466 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07008467
8468 // Touch Window 1
8469 PointF touchedPoint = {10, 10};
8470 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008471 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008472 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008473 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008474
8475 // Touch Window 2
8476 touchedPoint = {150, 150};
8477 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008478 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
8479 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008480
chaviw9eaa22c2020-07-01 16:21:27 -07008481 // Update the transform so rotation is set
8482 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008483 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008484 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008485 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008486}
8487
chaviw9eaa22c2020-07-01 16:21:27 -07008488TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008489 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008490 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008491
8492 // Touch Window 1
8493 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8494 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008495 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008496
8497 // Touch Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008498 // Since this is part of the same touch gesture that has already been dispatched to Window 1,
8499 // the touch stream from Window 2 will be merged with the stream in Window 1. The merged stream
8500 // will continue to be dispatched through Window 1.
chaviw9eaa22c2020-07-01 16:21:27 -07008501 touchedPoints.push_back(PointF{150, 150});
8502 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008503 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008504
chaviw9eaa22c2020-07-01 16:21:27 -07008505 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008506 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008507 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008508
chaviw9eaa22c2020-07-01 16:21:27 -07008509 // Update the transform so rotation is set for Window 2
8510 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008511 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008512 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008513 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008514}
8515
chaviw9eaa22c2020-07-01 16:21:27 -07008516TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008517 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008518 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008519
8520 // Touch Window 1
8521 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8522 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008523 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008524
8525 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07008526 touchedPoints.push_back(PointF{150, 150});
8527 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008528
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008529 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008530
8531 // Move both windows
8532 touchedPoints = {{20, 20}, {175, 175}};
8533 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8534 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8535
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008536 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008537
chaviw9eaa22c2020-07-01 16:21:27 -07008538 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008539 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008540 expectedPoints.pop_back();
8541
8542 // Touch Window 2
8543 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008544 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008545 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008546 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008547
8548 // Move both windows
8549 touchedPoints = {{20, 20}, {175, 175}};
8550 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8551 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8552
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008553 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008554}
8555
8556TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
8557 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008558 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008559
8560 // Touch Window 1
8561 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8562 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008563 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008564
8565 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07008566 touchedPoints.push_back(PointF{150, 150});
8567 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008568
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008569 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008570
8571 // Move both windows
8572 touchedPoints = {{20, 20}, {175, 175}};
8573 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8574 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8575
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008576 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008577}
8578
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07008579/**
8580 * When one of the windows is slippery, the touch should not slip into the other window with the
8581 * same input channel.
8582 */
8583TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
8584 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008585 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07008586
8587 // Touch down in window 1
8588 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8589 ADISPLAY_ID_DEFAULT, {{50, 50}}));
8590 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
8591
8592 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
8593 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
8594 // getting generated.
8595 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8596 ADISPLAY_ID_DEFAULT, {{150, 150}}));
8597
8598 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
8599}
8600
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008601/**
8602 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
8603 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
8604 * that the pointer is hovering over may have a different transform.
8605 */
8606TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008607 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008608
8609 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008610 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
8611 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8612 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008613 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
8614 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008615 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008616 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8617 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
8618 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008619 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008620 consumeMotionEvent(mWindow2, ACTION_HOVER_ENTER,
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008621 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
8622}
8623
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008624class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
8625 virtual void SetUp() override {
8626 InputDispatcherTest::SetUp();
8627
Chris Yea209fde2020-07-22 13:54:51 -07008628 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008629 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008630 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
8631 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008632 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008633 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07008634 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008635
8636 // Set focused application.
8637 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8638
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008639 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008640 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008641 mWindow->consumeFocusEvent(true);
8642 }
8643
8644 virtual void TearDown() override {
8645 InputDispatcherTest::TearDown();
8646 mWindow.clear();
8647 }
8648
8649protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008650 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07008651 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008652 sp<FakeWindowHandle> mWindow;
8653 static constexpr PointF WINDOW_LOCATION = {20, 20};
8654
8655 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008656 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
8657 .x(WINDOW_LOCATION.x)
8658 .y(WINDOW_LOCATION.y);
8659 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8660 .pointer(touchingPointer)
8661 .build());
8662 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8663 .pointer(touchingPointer)
8664 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008665 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008666
8667 sp<FakeWindowHandle> addSpyWindow() {
8668 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008669 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008670 spy->setTrustedOverlay(true);
8671 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008672 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008673 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008674 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008675 return spy;
8676 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008677};
8678
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008679// Send a tap and respond, which should not cause an ANR.
8680TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
8681 tapOnWindow();
8682 mWindow->consumeMotionDown();
8683 mWindow->consumeMotionUp();
8684 ASSERT_TRUE(mDispatcher->waitForIdle());
8685 mFakePolicy->assertNotifyAnrWasNotCalled();
8686}
8687
8688// Send a regular key and respond, which should not cause an ANR.
8689TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008690 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008691 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8692 ASSERT_TRUE(mDispatcher->waitForIdle());
8693 mFakePolicy->assertNotifyAnrWasNotCalled();
8694}
8695
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008696TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
8697 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008698 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008699 mWindow->consumeFocusEvent(false);
8700
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008701 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008702 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8703 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00008704 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008705 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008706 // Key will not go to window because we have no focused window.
8707 // The 'no focused window' ANR timer should start instead.
8708
8709 // Now, the focused application goes away.
8710 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
8711 // The key should get dropped and there should be no ANR.
8712
8713 ASSERT_TRUE(mDispatcher->waitForIdle());
8714 mFakePolicy->assertNotifyAnrWasNotCalled();
8715}
8716
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008717// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008718// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8719// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008720TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008721 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008722 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008723 WINDOW_LOCATION));
8724
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008725 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008726 ASSERT_TRUE(sequenceNum);
8727 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008728 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008729
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008730 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008731 mWindow->consumeMotionEvent(
8732 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008733 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008734 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008735}
8736
8737// Send a key to the app and have the app not respond right away.
8738TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
8739 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008740 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008741 const auto [sequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008742 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008743 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008744 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008745 ASSERT_TRUE(mDispatcher->waitForIdle());
8746}
8747
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008748// We have a focused application, but no focused window
8749TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008750 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008751 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008752 mWindow->consumeFocusEvent(false);
8753
8754 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008755 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008756 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008757 WINDOW_LOCATION));
8758 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
8759 mDispatcher->waitForIdle();
8760 mFakePolicy->assertNotifyAnrWasNotCalled();
8761
8762 // Once a focused event arrives, we get an ANR for this application
8763 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8764 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008765 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008766 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008767 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008768 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008769 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07008770 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008771 ASSERT_TRUE(mDispatcher->waitForIdle());
8772}
8773
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008774/**
8775 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
8776 * there will not be an ANR.
8777 */
8778TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
8779 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008780 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008781 mWindow->consumeFocusEvent(false);
8782
8783 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07008784 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
8785 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008786 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
8787 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
8788
8789 // Define a valid key down event that is stale (too old).
8790 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00008791 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00008792 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008793
8794 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
8795
8796 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00008797 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008798 InputEventInjectionSync::WAIT_FOR_RESULT,
8799 INJECT_EVENT_TIMEOUT, policyFlags);
8800 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
8801 << "Injection should fail because the event is stale";
8802
8803 ASSERT_TRUE(mDispatcher->waitForIdle());
8804 mFakePolicy->assertNotifyAnrWasNotCalled();
8805 mWindow->assertNoEvents();
8806}
8807
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008808// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008809// Make sure that we don't notify policy twice about the same ANR.
8810TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008811 const std::chrono::duration appTimeout = 400ms;
8812 mApplication->setDispatchingTimeout(appTimeout);
8813 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8814
Vishnu Nair47074b82020-08-14 11:54:47 -07008815 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008816 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008817 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008818
8819 // Once a focused event arrives, we get an ANR for this application
8820 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8821 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008822 const std::chrono::duration eventInjectionTimeout = 100ms;
8823 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008824 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008825 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008826 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
8827 /*allowKeyRepeat=*/false);
8828 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
8829 << "result=" << ftl::enum_string(result);
8830 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
8831 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
8832 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
8833 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008834
Vishnu Naire4df8752022-09-08 09:17:55 -07008835 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008836 // ANR should not be raised again. It is up to policy to do that if it desires.
8837 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008838
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008839 // If we now get a focused window, the ANR should stop, but the policy handles that via
8840 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008841 ASSERT_TRUE(mDispatcher->waitForIdle());
8842}
8843
8844// We have a focused application, but no focused window
8845TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008846 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008847 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008848 mWindow->consumeFocusEvent(false);
8849
8850 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008851 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008852
Vishnu Naire4df8752022-09-08 09:17:55 -07008853 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8854 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008855
8856 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008857 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008858 ASSERT_TRUE(mDispatcher->waitForIdle());
8859 mWindow->assertNoEvents();
8860}
8861
8862/**
8863 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
8864 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
8865 * If we process 1 of the events, but ANR on the second event with the same timestamp,
8866 * the ANR mechanism should still work.
8867 *
8868 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
8869 * DOWN event, while not responding on the second one.
8870 */
8871TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
8872 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008873 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008874 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8875 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8876 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008877 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008878
8879 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008880 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008881 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8882 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8883 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008884 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008885
8886 // We have now sent down and up. Let's consume first event and then ANR on the second.
8887 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8888 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008889 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008890}
8891
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008892// A spy window can receive an ANR
8893TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
8894 sp<FakeWindowHandle> spy = addSpyWindow();
8895
8896 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008897 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008898 WINDOW_LOCATION));
8899 mWindow->consumeMotionDown();
8900
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008901 const auto [sequenceNum, _] = spy->receiveEvent(); // ACTION_DOWN
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008902 ASSERT_TRUE(sequenceNum);
8903 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008904 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008905
8906 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008907 spy->consumeMotionEvent(
8908 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008909 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008910 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008911}
8912
8913// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008914// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008915TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
8916 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008917
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008918 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008919 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008920 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008921 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008922
8923 // Stuck on the ACTION_UP
8924 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008925 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008926
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008927 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008928 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008929 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8930 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008931
8932 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8933 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008934 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008935 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008936 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008937}
8938
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008939// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008940// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008941TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
8942 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008943
8944 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008945 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8946 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008947
8948 mWindow->consumeMotionDown();
8949 // Stuck on the ACTION_UP
8950 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008951 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008952
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008953 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008954 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008955 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8956 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008957
8958 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8959 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008960 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008961 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008962 spy->assertNoEvents();
8963}
8964
8965TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008966 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008967
Prabir Pradhanfb549072023-10-05 19:17:36 +00008968 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008969
8970 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008971 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008972 WINDOW_LOCATION));
8973
8974 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8975 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
8976 ASSERT_TRUE(consumeSeq);
8977
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008978 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
8979 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008980
8981 monitor.finishEvent(*consumeSeq);
8982 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
8983
8984 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008985 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008986}
8987
8988// If a window is unresponsive, then you get anr. if the window later catches up and starts to
8989// process events, you don't get an anr. When the window later becomes unresponsive again, you
8990// get an ANR again.
8991// 1. tap -> block on ACTION_UP -> receive ANR
8992// 2. consume all pending events (= queue becomes healthy again)
8993// 3. tap again -> block on ACTION_UP again -> receive ANR second time
8994TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
8995 tapOnWindow();
8996
8997 mWindow->consumeMotionDown();
8998 // Block on ACTION_UP
8999 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009000 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009001 mWindow->consumeMotionUp(); // Now the connection should be healthy again
9002 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08009003 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009004 mWindow->assertNoEvents();
9005
9006 tapOnWindow();
9007 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08009008 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009009 mWindow->consumeMotionUp();
9010
9011 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08009012 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009013 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009014 mWindow->assertNoEvents();
9015}
9016
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009017// If a connection remains unresponsive for a while, make sure policy is only notified once about
9018// it.
9019TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009020 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009021 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009022 WINDOW_LOCATION));
9023
9024 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009025 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009026 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009027 // 'notifyConnectionUnresponsive' should only be called once per connection
9028 mFakePolicy->assertNotifyAnrWasNotCalled();
9029 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009030 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009031 mWindow->consumeMotionEvent(
9032 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009033 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009034 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08009035 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009036 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009037}
9038
9039/**
9040 * 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 -07009041 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009042 */
9043TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009044 // The timeouts in this test are established by relying on the fact that the "key waiting for
9045 // events timeout" is equal to 500ms.
9046 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009047 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009048 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009049
9050 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009051 const auto& [downSequenceNum, downEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009052 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009053 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009054 ASSERT_TRUE(upSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009055
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009056 // Don't finish the events yet, and send a key
9057 mDispatcher->notifyKey(
9058 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
9059 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9060 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009061 // Key will not be sent to the window, yet, because the window is still processing events
9062 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009063 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009064 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009065
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009066 std::this_thread::sleep_for(400ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009067 // if we wait long enough though, dispatcher will give up, and still send the key
9068 // to the focused window, even though we have not yet finished the motion event
9069 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9070 mWindow->finishEvent(*downSequenceNum);
9071 mWindow->finishEvent(*upSequenceNum);
9072}
9073
9074/**
9075 * If a window is processing a motion event, and then a key event comes in, the key event should
9076 * not go to the focused window until the motion is processed.
9077 * If then a new motion comes in, then the pending key event should be going to the currently
9078 * focused window right away.
9079 */
9080TEST_F(InputDispatcherSingleWindowAnr,
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009081 PendingKey_IsDeliveredWhileMotionIsProcessingAndNewTouchComesIn) {
9082 // The timeouts in this test are established by relying on the fact that the "key waiting for
9083 // events timeout" is equal to 500ms.
9084 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009085 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009086 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009087
9088 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009089 const auto& [downSequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009090 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009091 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009092 ASSERT_TRUE(upSequenceNum);
9093 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08009094 mDispatcher->notifyKey(
9095 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
9096 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9097 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009098 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009099 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009100
9101 // Now tap down again. It should cause the pending key to go to the focused window right away.
9102 tapOnWindow();
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009103 // Now that we tapped, we should receive the key immediately.
9104 // Since there's still room for slowness, we use 200ms, which is much less than
9105 // the "key waiting for events' timeout of 500ms minus the already waited 100ms duration.
9106 std::unique_ptr<InputEvent> keyEvent = mWindow->consume(200ms);
9107 ASSERT_NE(nullptr, keyEvent);
9108 ASSERT_EQ(InputEventType::KEY, keyEvent->getType());
9109 ASSERT_THAT(static_cast<KeyEvent&>(*keyEvent), WithKeyAction(AKEY_EVENT_ACTION_DOWN));
9110 // it doesn't matter that we haven't ack'd the other events yet. We can finish events in any
9111 // order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009112 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
9113 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08009114 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9115 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009116 mWindow->assertNoEvents();
9117}
9118
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07009119/**
9120 * Send an event to the app and have the app not respond right away.
9121 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
9122 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
9123 * At some point, the window becomes responsive again.
9124 * Ensure that subsequent events get dropped, and the next gesture is delivered.
9125 */
9126TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
9127 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9128 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
9129 .build());
9130
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009131 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07009132 ASSERT_TRUE(sequenceNum);
9133 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9134 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
9135
9136 mWindow->finishEvent(*sequenceNum);
9137 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
9138 ASSERT_TRUE(mDispatcher->waitForIdle());
9139 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
9140
9141 // Now that the window is responsive, let's continue the gesture.
9142 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9143 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9144 .build());
9145
9146 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9147 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9148 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
9149 .build());
9150
9151 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9152 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9153 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
9154 .build());
9155 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9156 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9157 .build());
9158 // We already canceled this pointer, so the window shouldn't get any new events.
9159 mWindow->assertNoEvents();
9160
9161 // Start another one.
9162 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9163 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
9164 .build());
9165 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9166}
9167
Prabir Pradhanfc364722024-02-08 17:51:20 +00009168// Send an event to the app and have the app not respond right away. Then remove the app window.
9169// When the window is removed, the dispatcher will cancel the events for that window.
9170// So InputDispatcher will enqueue ACTION_CANCEL event as well.
9171TEST_F(InputDispatcherSingleWindowAnr, AnrAfterWindowRemoval) {
9172 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9173 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9174 {WINDOW_LOCATION}));
9175
9176 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
9177 ASSERT_TRUE(sequenceNum);
9178
9179 // Remove the window, but the input channel should remain alive.
9180 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
9181
9182 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9183 // Since the window was removed, Dispatcher does not know the PID associated with the window
9184 // anymore, so the policy is notified without the PID.
9185 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken(),
9186 /*pid=*/std::nullopt);
9187
9188 mWindow->finishEvent(*sequenceNum);
9189 // The cancellation was generated when the window was removed, along with the focus event.
9190 mWindow->consumeMotionEvent(
9191 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
9192 mWindow->consumeFocusEvent(false);
9193 ASSERT_TRUE(mDispatcher->waitForIdle());
9194 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
9195}
9196
9197// Send an event to the app and have the app not respond right away. Wait for the policy to be
9198// notified of the unresponsive window, then remove the app window.
9199TEST_F(InputDispatcherSingleWindowAnr, AnrFollowedByWindowRemoval) {
9200 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9201 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9202 {WINDOW_LOCATION}));
9203
9204 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
9205 ASSERT_TRUE(sequenceNum);
9206 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9207 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
9208
9209 // Remove the window, but the input channel should remain alive.
9210 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
9211
9212 mWindow->finishEvent(*sequenceNum);
9213 // The cancellation was generated during the ANR, and the window lost focus when it was removed.
9214 mWindow->consumeMotionEvent(
9215 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
9216 mWindow->consumeFocusEvent(false);
9217 ASSERT_TRUE(mDispatcher->waitForIdle());
9218 // Since the window was removed, Dispatcher does not know the PID associated with the window
9219 // becoming responsive, so the policy is notified without the PID.
9220 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
9221}
9222
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009223class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
9224 virtual void SetUp() override {
9225 InputDispatcherTest::SetUp();
9226
Chris Yea209fde2020-07-22 13:54:51 -07009227 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009228 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009229 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
9230 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009231 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009232 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009233 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009234
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009235 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
9236 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009237 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009238 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009239
9240 // Set focused application.
9241 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07009242 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009243
9244 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009245 mDispatcher->onWindowInfosChanged(
9246 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009247 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009248 mFocusedWindow->consumeFocusEvent(true);
9249 }
9250
9251 virtual void TearDown() override {
9252 InputDispatcherTest::TearDown();
9253
9254 mUnfocusedWindow.clear();
9255 mFocusedWindow.clear();
9256 }
9257
9258protected:
Chris Yea209fde2020-07-22 13:54:51 -07009259 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009260 sp<FakeWindowHandle> mUnfocusedWindow;
9261 sp<FakeWindowHandle> mFocusedWindow;
9262 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
9263 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
9264 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
9265
9266 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
9267
9268 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
9269
9270private:
9271 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009272 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009273 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009274 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009275 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009276 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009277 location));
9278 }
9279};
9280
9281// If we have 2 windows that are both unresponsive, the one with the shortest timeout
9282// should be ANR'd first.
9283TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009284 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009285 injectMotionEvent(*mDispatcher,
9286 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9287 AINPUT_SOURCE_TOUCHSCREEN)
9288 .pointer(PointerBuilder(0, ToolType::FINGER)
9289 .x(FOCUSED_WINDOW_LOCATION.x)
9290 .y(FOCUSED_WINDOW_LOCATION.y))
9291 .build()));
9292 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9293 injectMotionEvent(*mDispatcher,
9294 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
9295 AINPUT_SOURCE_TOUCHSCREEN)
9296 .pointer(PointerBuilder(0, ToolType::FINGER)
9297 .x(FOCUSED_WINDOW_LOCATION.x)
9298 .y(FOCUSED_WINDOW_LOCATION.y))
9299 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009300 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009301 mFocusedWindow->consumeMotionUp();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009302 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009303 // We consumed all events, so no ANR
9304 ASSERT_TRUE(mDispatcher->waitForIdle());
9305 mFakePolicy->assertNotifyAnrWasNotCalled();
9306
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009307 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009308 injectMotionEvent(*mDispatcher,
9309 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9310 AINPUT_SOURCE_TOUCHSCREEN)
9311 .pointer(PointerBuilder(0, ToolType::FINGER)
9312 .x(FOCUSED_WINDOW_LOCATION.x)
9313 .y(FOCUSED_WINDOW_LOCATION.y))
9314 .build()));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009315 const auto [unfocusedSequenceNum, _] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009316 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009317
9318 const std::chrono::duration timeout =
9319 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009320 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009321
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009322 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009323 mFocusedWindow->consumeMotionDown();
9324 // This cancel is generated because the connection was unresponsive
9325 mFocusedWindow->consumeMotionCancel();
9326 mFocusedWindow->assertNoEvents();
9327 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009328 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009329 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9330 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009331 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009332}
9333
9334// If we have 2 windows with identical timeouts that are both unresponsive,
9335// it doesn't matter which order they should have ANR.
9336// But we should receive ANR for both.
9337TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
9338 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009339 mUnfocusedWindow->setDispatchingTimeout(
9340 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009341 mDispatcher->onWindowInfosChanged(
9342 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009343
9344 tapOnFocusedWindow();
9345 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009346 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009347 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
9348 mFocusedWindow->getDispatchingTimeout(
9349 DISPATCHING_TIMEOUT)),
9350 mFakePolicy->getUnresponsiveWindowToken(0ms)};
9351
9352 ASSERT_THAT(anrConnectionTokens,
9353 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
9354 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009355
9356 ASSERT_TRUE(mDispatcher->waitForIdle());
9357 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009358
9359 mFocusedWindow->consumeMotionDown();
9360 mFocusedWindow->consumeMotionUp();
9361 mUnfocusedWindow->consumeMotionOutside();
9362
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009363 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
9364 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009365
9366 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009367 ASSERT_THAT(responsiveTokens,
9368 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
9369 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009370 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009371}
9372
9373// If a window is already not responding, the second tap on the same window should be ignored.
9374// We should also log an error to account for the dropped event (not tested here).
9375// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
9376TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
9377 tapOnFocusedWindow();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009378 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009379 // Receive the events, but don't respond
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009380 const auto [downEventSequenceNum, downEvent] = mFocusedWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009381 ASSERT_TRUE(downEventSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009382 const auto [upEventSequenceNum, upEvent] = mFocusedWindow->receiveEvent(); // ACTION_UP
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009383 ASSERT_TRUE(upEventSequenceNum);
9384 const std::chrono::duration timeout =
9385 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009386 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009387
9388 // Tap once again
9389 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009390 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009391 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009392 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009393 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009394 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009395 FOCUSED_WINDOW_LOCATION));
9396 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
9397 // valid touch target
9398 mUnfocusedWindow->assertNoEvents();
9399
9400 // Consume the first tap
9401 mFocusedWindow->finishEvent(*downEventSequenceNum);
9402 mFocusedWindow->finishEvent(*upEventSequenceNum);
9403 ASSERT_TRUE(mDispatcher->waitForIdle());
9404 // The second tap did not go to the focused window
9405 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009406 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08009407 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9408 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009409 mFakePolicy->assertNotifyAnrWasNotCalled();
9410}
9411
9412// If you tap outside of all windows, there will not be ANR
9413TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009414 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009415 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009416 LOCATION_OUTSIDE_ALL_WINDOWS));
9417 ASSERT_TRUE(mDispatcher->waitForIdle());
9418 mFakePolicy->assertNotifyAnrWasNotCalled();
9419}
9420
9421// Since the focused window is paused, tapping on it should not produce any events
9422TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
9423 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009424 mDispatcher->onWindowInfosChanged(
9425 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009426
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009427 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009428 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009429 FOCUSED_WINDOW_LOCATION));
9430
9431 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
9432 ASSERT_TRUE(mDispatcher->waitForIdle());
9433 // Should not ANR because the window is paused, and touches shouldn't go to it
9434 mFakePolicy->assertNotifyAnrWasNotCalled();
9435
9436 mFocusedWindow->assertNoEvents();
9437 mUnfocusedWindow->assertNoEvents();
9438}
9439
9440/**
9441 * 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 -07009442 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009443 * If a different window becomes focused at this time, the key should go to that window instead.
9444 *
9445 * Warning!!!
9446 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
9447 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009448 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009449 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
9450 *
9451 * If that value changes, this test should also change.
9452 */
9453TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
9454 // Set a long ANR timeout to prevent it from triggering
9455 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009456 mDispatcher->onWindowInfosChanged(
9457 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009458
9459 tapOnUnfocusedWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009460 const auto [downSequenceNum, downEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009461 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009462 const auto [upSequenceNum, upEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009463 ASSERT_TRUE(upSequenceNum);
9464 // Don't finish the events yet, and send a key
9465 // Injection will succeed because we will eventually give up and send the key to the focused
9466 // window even if motions are still being processed.
9467
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009468 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009469 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9470 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009471 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009472 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009473 // and the key remains pending, waiting for the touch events to be processed.
9474 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
9475 // under the hood.
9476 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
9477 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009478
9479 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07009480 mFocusedWindow->setFocusable(false);
9481 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009482 mDispatcher->onWindowInfosChanged(
9483 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009484 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009485
9486 // Focus events should precede the key events
9487 mUnfocusedWindow->consumeFocusEvent(true);
9488 mFocusedWindow->consumeFocusEvent(false);
9489
9490 // Finish the tap events, which should unblock dispatcher
9491 mUnfocusedWindow->finishEvent(*downSequenceNum);
9492 mUnfocusedWindow->finishEvent(*upSequenceNum);
9493
9494 // Now that all queues are cleared and no backlog in the connections, the key event
9495 // can finally go to the newly focused "mUnfocusedWindow".
9496 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9497 mFocusedWindow->assertNoEvents();
9498 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009499 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009500}
9501
9502// When the touch stream is split across 2 windows, and one of them does not respond,
9503// then ANR should be raised and the touch should be canceled for the unresponsive window.
9504// The other window should not be affected by that.
9505TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
9506 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00009507 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9508 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9509 {FOCUSED_WINDOW_LOCATION}));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009510 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009511
9512 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00009513 mDispatcher->notifyMotion(
9514 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9515 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009516
9517 const std::chrono::duration timeout =
9518 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009519 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009520
9521 mUnfocusedWindow->consumeMotionDown();
9522 mFocusedWindow->consumeMotionDown();
9523 // Focused window may or may not receive ACTION_MOVE
9524 // But it should definitely receive ACTION_CANCEL due to the ANR
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009525 const auto [moveOrCancelSequenceNum, event] = mFocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009526 ASSERT_TRUE(moveOrCancelSequenceNum);
9527 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
9528 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009529 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009530 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
9531 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
9532 mFocusedWindow->consumeMotionCancel();
9533 } else {
9534 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
9535 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009536 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009537 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9538 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009539
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009540 mUnfocusedWindow->assertNoEvents();
9541 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009542 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009543}
9544
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009545/**
9546 * If we have no focused window, and a key comes in, we start the ANR timer.
9547 * The focused application should add a focused window before the timer runs out to prevent ANR.
9548 *
9549 * If the user touches another application during this time, the key should be dropped.
9550 * Next, if a new focused window comes in, without toggling the focused application,
9551 * then no ANR should occur.
9552 *
9553 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
9554 * but in some cases the policy may not update the focused application.
9555 */
9556TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
9557 std::shared_ptr<FakeApplicationHandle> focusedApplication =
9558 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07009559 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009560 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
9561 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
9562 mFocusedWindow->setFocusable(false);
9563
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009564 mDispatcher->onWindowInfosChanged(
9565 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009566 mFocusedWindow->consumeFocusEvent(false);
9567
9568 // Send a key. The ANR timer should start because there is no focused window.
9569 // 'focusedApplication' will get blamed if this timer completes.
9570 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009571 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009572 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9573 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00009574 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009575 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009576
9577 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
9578 // then the injected touches won't cause the focused event to get dropped.
9579 // The dispatcher only checks for whether the queue should be pruned upon queueing.
9580 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
9581 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
9582 // For this test, it means that the key would get delivered to the window once it becomes
9583 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009584 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009585
9586 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00009587 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9588 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9589 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009590
9591 // We do not consume the motion right away, because that would require dispatcher to first
9592 // process (== drop) the key event, and by that time, ANR will be raised.
9593 // Set the focused window first.
9594 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009595 mDispatcher->onWindowInfosChanged(
9596 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009597 setFocusedWindow(mFocusedWindow);
9598 mFocusedWindow->consumeFocusEvent(true);
9599 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
9600 // to another application. This could be a bug / behaviour in the policy.
9601
9602 mUnfocusedWindow->consumeMotionDown();
9603
9604 ASSERT_TRUE(mDispatcher->waitForIdle());
9605 // Should not ANR because we actually have a focused window. It was just added too slowly.
9606 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
9607}
9608
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -08009609/**
9610 * If we are pruning input queue, we should never drop pointer events. Otherwise, we risk having
9611 * an inconsistent event stream inside the dispatcher. In this test, we make sure that the
9612 * dispatcher doesn't prune pointer events incorrectly.
9613 *
9614 * This test reproduces a crash in InputDispatcher.
9615 * To reproduce the crash, we need to simulate the conditions for "pruning input queue" to occur.
9616 *
9617 * Keep the currently focused application (mApplication), and have no focused window.
9618 * We set up two additional windows:
9619 * 1) The navigation bar window. This simulates the system "NavigationBar", which is used in the
9620 * 3-button navigation mode. This window injects a BACK button when it's touched. 2) The application
9621 * window. This window is not focusable, but is touchable.
9622 *
9623 * We first touch the navigation bar, which causes it to inject a key. Since there's no focused
9624 * window, the dispatcher doesn't process this key, and all other events inside dispatcher are now
9625 * blocked. The dispatcher is waiting for 'mApplication' to add a focused window.
9626 *
9627 * Now, we touch "Another window". This window is owned by a different application than
9628 * 'mApplication'. This causes the dispatcher to stop waiting for 'mApplication' to add a focused
9629 * window. Now, the "pruning input queue" behaviour should kick in, and the dispatcher should start
9630 * dropping the events from its queue. Ensure that no crash occurs.
9631 *
9632 * In this test, we are setting long timeouts to prevent ANRs and events dropped due to being stale.
9633 * This does not affect the test running time.
9634 */
9635TEST_F(InputDispatcherMultiWindowAnr, PruningInputQueueShouldNotDropPointerEvents) {
9636 std::shared_ptr<FakeApplicationHandle> systemUiApplication =
9637 std::make_shared<FakeApplicationHandle>();
9638 systemUiApplication->setDispatchingTimeout(3000ms);
9639 mFakePolicy->setStaleEventTimeout(3000ms);
9640 sp<FakeWindowHandle> navigationBar =
9641 sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
9642 ADISPLAY_ID_DEFAULT);
9643 navigationBar->setFocusable(false);
9644 navigationBar->setWatchOutsideTouch(true);
9645 navigationBar->setFrame(Rect(0, 0, 100, 100));
9646
9647 mApplication->setDispatchingTimeout(3000ms);
9648 // 'mApplication' is already focused, but we call it again here to make it explicit.
9649 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
9650
9651 std::shared_ptr<FakeApplicationHandle> anotherApplication =
9652 std::make_shared<FakeApplicationHandle>();
9653 sp<FakeWindowHandle> appWindow =
9654 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
9655 ADISPLAY_ID_DEFAULT);
9656 appWindow->setFocusable(false);
9657 appWindow->setFrame(Rect(100, 100, 200, 200));
9658
9659 mDispatcher->onWindowInfosChanged(
9660 {{*navigationBar->getInfo(), *appWindow->getInfo()}, {}, 0, 0});
9661 // 'mFocusedWindow' is no longer in the dispatcher window list, and therefore loses focus
9662 mFocusedWindow->consumeFocusEvent(false);
9663
9664 // Touch down the navigation bar. It consumes the touch and injects a key into the dispatcher
9665 // in response.
9666 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9667 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9668 .build());
9669 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9670
9671 // Key will not be sent anywhere because we have no focused window. It will remain pending.
9672 // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
9673 InputEventInjectionResult result =
9674 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9675 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
9676 /*allowKeyRepeat=*/false);
9677 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
9678
9679 // Finish the gesture - lift up finger and inject ACTION_UP key event
9680 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9681 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9682 .build());
9683 result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9684 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
9685 /*allowKeyRepeat=*/false);
9686 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
9687 // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
9688 // getting any events yet.
9689 navigationBar->assertNoEvents();
9690
9691 // Now touch "Another window". This touch is going to a different application than the one we
9692 // are waiting for (which is 'mApplication').
9693 // This should cause the dispatcher to drop the pending focus-dispatched events (like the key
9694 // trying to be injected) and to continue processing the rest of the events in the original
9695 // order.
9696 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9697 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
9698 .build());
9699 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_UP));
9700 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
9701 appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9702
9703 appWindow->assertNoEvents();
9704 navigationBar->assertNoEvents();
9705}
9706
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009707// These tests ensure we cannot send touch events to a window that's positioned behind a window
9708// that has feature NO_INPUT_CHANNEL.
9709// Layout:
9710// Top (closest to user)
9711// mNoInputWindow (above all windows)
9712// mBottomWindow
9713// Bottom (furthest from user)
9714class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
9715 virtual void SetUp() override {
9716 InputDispatcherTest::SetUp();
9717
9718 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009719 mNoInputWindow =
9720 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
9721 "Window without input channel", ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009722 /*createInputChannel=*/false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009723 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009724 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
9725 // It's perfectly valid for this window to not have an associated input channel
9726
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009727 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
9728 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009729 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
9730
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009731 mDispatcher->onWindowInfosChanged(
9732 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009733 }
9734
9735protected:
9736 std::shared_ptr<FakeApplicationHandle> mApplication;
9737 sp<FakeWindowHandle> mNoInputWindow;
9738 sp<FakeWindowHandle> mBottomWindow;
9739};
9740
9741TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
9742 PointF touchedPoint = {10, 10};
9743
Prabir Pradhan678438e2023-04-13 19:32:51 +00009744 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9745 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9746 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009747
9748 mNoInputWindow->assertNoEvents();
9749 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
9750 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
9751 // and therefore should prevent mBottomWindow from receiving touches
9752 mBottomWindow->assertNoEvents();
9753}
9754
9755/**
9756 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
9757 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
9758 */
9759TEST_F(InputDispatcherMultiWindowOcclusionTests,
9760 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009761 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
9762 "Window with input channel and NO_INPUT_CHANNEL",
9763 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009764
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009765 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009766 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009767 mDispatcher->onWindowInfosChanged(
9768 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009769
9770 PointF touchedPoint = {10, 10};
9771
Prabir Pradhan678438e2023-04-13 19:32:51 +00009772 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9773 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9774 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009775
9776 mNoInputWindow->assertNoEvents();
9777 mBottomWindow->assertNoEvents();
9778}
9779
Vishnu Nair958da932020-08-21 17:12:37 -07009780class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
9781protected:
9782 std::shared_ptr<FakeApplicationHandle> mApp;
9783 sp<FakeWindowHandle> mWindow;
9784 sp<FakeWindowHandle> mMirror;
9785
9786 virtual void SetUp() override {
9787 InputDispatcherTest::SetUp();
9788 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009789 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009790 mMirror = mWindow->clone(ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07009791 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
9792 mWindow->setFocusable(true);
9793 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009794 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009795 }
9796};
9797
9798TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
9799 // Request focus on a mirrored window
9800 setFocusedWindow(mMirror);
9801
9802 // window gets focused
9803 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009804 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009805 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009806 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
9807}
9808
9809// A focused & mirrored window remains focused only if the window and its mirror are both
9810// focusable.
9811TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
9812 setFocusedWindow(mMirror);
9813
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009814 // window gets focused because it is above the mirror
Vishnu Nair958da932020-08-21 17:12:37 -07009815 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009816 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009817 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009818 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009819 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009820 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009821 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9822
9823 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009824 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009825
9826 // window loses focus since one of the windows associated with the token in not focusable
9827 mWindow->consumeFocusEvent(false);
9828
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009829 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009830 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009831 mWindow->assertNoEvents();
9832}
9833
9834// A focused & mirrored window remains focused until the window and its mirror both become
9835// invisible.
9836TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
9837 setFocusedWindow(mMirror);
9838
9839 // window gets focused
9840 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009841 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009842 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009843 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009844 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009845 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009846 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9847
9848 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009849 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009850
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009851 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009852 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009853 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009854 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009855 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009856 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9857
9858 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009859 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009860
9861 // window loses focus only after all windows associated with the token become invisible.
9862 mWindow->consumeFocusEvent(false);
9863
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009864 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009865 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009866 mWindow->assertNoEvents();
9867}
9868
9869// A focused & mirrored window remains focused until both windows are removed.
9870TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
9871 setFocusedWindow(mMirror);
9872
9873 // window gets focused
9874 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009875 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009876 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009877 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009878 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009879 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009880 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9881
9882 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009883 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009884
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009885 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009886 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009887 mMirror->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009888 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009889 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009890 mMirror->consumeKeyUp(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07009891
9892 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009893 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009894 mWindow->consumeFocusEvent(false);
9895
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009896 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009897 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009898 mWindow->assertNoEvents();
9899}
9900
9901// Focus request can be pending until one window becomes visible.
9902TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
9903 // Request focus on an invisible mirror.
9904 mWindow->setVisible(false);
9905 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009906 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009907 setFocusedWindow(mMirror);
9908
9909 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009910 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009911 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9912 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07009913
9914 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009915 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009916
9917 // window gets focused
9918 mWindow->consumeFocusEvent(true);
9919 // window gets the pending key event
9920 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9921}
Prabir Pradhan99987712020-11-10 18:43:05 -08009922
9923class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
9924protected:
9925 std::shared_ptr<FakeApplicationHandle> mApp;
9926 sp<FakeWindowHandle> mWindow;
9927 sp<FakeWindowHandle> mSecondWindow;
9928
9929 void SetUp() override {
9930 InputDispatcherTest::SetUp();
9931 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009932 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009933 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009934 mSecondWindow =
9935 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009936 mSecondWindow->setFocusable(true);
9937
9938 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009939 mDispatcher->onWindowInfosChanged(
9940 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08009941
9942 setFocusedWindow(mWindow);
9943 mWindow->consumeFocusEvent(true);
9944 }
9945
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009946 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009947 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08009948 }
9949
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009950 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
9951 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08009952 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009953 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
9954 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009955 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009956 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08009957 }
9958};
9959
9960TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
9961 // Ensure that capture cannot be obtained for unfocused windows.
9962 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
9963 mFakePolicy->assertSetPointerCaptureNotCalled();
9964 mSecondWindow->assertNoEvents();
9965
9966 // Ensure that capture can be enabled from the focus window.
9967 requestAndVerifyPointerCapture(mWindow, true);
9968
9969 // Ensure that capture cannot be disabled from a window that does not have capture.
9970 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
9971 mFakePolicy->assertSetPointerCaptureNotCalled();
9972
9973 // Ensure that capture can be disabled from the window with capture.
9974 requestAndVerifyPointerCapture(mWindow, false);
9975}
9976
9977TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009978 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009979
9980 setFocusedWindow(mSecondWindow);
9981
9982 // Ensure that the capture disabled event was sent first.
9983 mWindow->consumeCaptureEvent(false);
9984 mWindow->consumeFocusEvent(false);
9985 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009986 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009987
9988 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009989 notifyPointerCaptureChanged({});
9990 notifyPointerCaptureChanged(request);
9991 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08009992 mWindow->assertNoEvents();
9993 mSecondWindow->assertNoEvents();
9994 mFakePolicy->assertSetPointerCaptureNotCalled();
9995}
9996
9997TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009998 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009999
10000 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010001 notifyPointerCaptureChanged({});
10002 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -080010003
10004 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010005 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -080010006 mWindow->consumeCaptureEvent(false);
10007 mWindow->assertNoEvents();
10008}
10009
Prabir Pradhan167e6d92021-02-04 16:18:17 -080010010TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
10011 requestAndVerifyPointerCapture(mWindow, true);
10012
10013 // The first window loses focus.
10014 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010015 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080010016 mWindow->consumeCaptureEvent(false);
10017
10018 // Request Pointer Capture from the second window before the notification from InputReader
10019 // arrives.
10020 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010021 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080010022
10023 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010024 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -080010025
10026 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010027 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080010028
10029 mSecondWindow->consumeFocusEvent(true);
10030 mSecondWindow->consumeCaptureEvent(true);
10031}
10032
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010033TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
10034 // App repeatedly enables and disables capture.
10035 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
10036 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
10037 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
10038 mFakePolicy->assertSetPointerCaptureCalled(false);
10039 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
10040 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
10041
10042 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
10043 // first request is now stale, this should do nothing.
10044 notifyPointerCaptureChanged(firstRequest);
10045 mWindow->assertNoEvents();
10046
10047 // InputReader notifies that the second request was enabled.
10048 notifyPointerCaptureChanged(secondRequest);
10049 mWindow->consumeCaptureEvent(true);
10050}
10051
Prabir Pradhan7092e262022-05-03 16:51:09 +000010052TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
10053 requestAndVerifyPointerCapture(mWindow, true);
10054
10055 // App toggles pointer capture off and on.
10056 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
10057 mFakePolicy->assertSetPointerCaptureCalled(false);
10058
10059 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
10060 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
10061
10062 // InputReader notifies that the latest "enable" request was processed, while skipping over the
10063 // preceding "disable" request.
10064 notifyPointerCaptureChanged(enableRequest);
10065
10066 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
10067 // any notifications.
10068 mWindow->assertNoEvents();
10069}
10070
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010071/**
10072 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
10073 * mouse movements don't affect the previous mouse hovering state.
10074 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
10075 * HOVER_MOVE events).
10076 */
10077TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
10078 // Mouse hover on the window
10079 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
10080 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
10081 .build());
10082 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
10083 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
10084 .build());
10085
10086 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
10087 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
10088
10089 // Start pointer capture
10090 requestAndVerifyPointerCapture(mWindow, true);
10091
10092 // Send some relative mouse movements and receive them in the window.
10093 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
10094 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
10095 .build());
10096 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
10097 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
10098
10099 // Stop pointer capture
10100 requestAndVerifyPointerCapture(mWindow, false);
10101
10102 // Continue hovering on the window
10103 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
10104 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
10105 .build());
10106 mWindow->consumeMotionEvent(
10107 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
10108
10109 mWindow->assertNoEvents();
10110}
10111
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010112class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
10113protected:
10114 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +000010115
10116 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
10117 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
10118
10119 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
10120 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
10121
10122 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
10123 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
10124 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
10125 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
10126 MAXIMUM_OBSCURING_OPACITY);
10127
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010128 static constexpr gui::Uid TOUCHED_APP_UID{10001};
10129 static constexpr gui::Uid APP_B_UID{10002};
10130 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010131
10132 sp<FakeWindowHandle> mTouchWindow;
10133
10134 virtual void SetUp() override {
10135 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010136 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010137 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
10138 }
10139
10140 virtual void TearDown() override {
10141 InputDispatcherTest::TearDown();
10142 mTouchWindow.clear();
10143 }
10144
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010145 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -050010146 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010147 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010148 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010149 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010150 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010151 return window;
10152 }
10153
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010154 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010155 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
10156 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010157 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010158 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010159 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010160 return window;
10161 }
10162
10163 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010164 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10165 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10166 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010167 }
10168};
10169
10170TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010171 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010172 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010173 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010174
10175 touch();
10176
10177 mTouchWindow->assertNoEvents();
10178}
10179
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010180TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +000010181 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
10182 const sp<FakeWindowHandle>& w =
10183 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010184 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010185
10186 touch();
10187
10188 mTouchWindow->assertNoEvents();
10189}
10190
10191TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010192 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
10193 const sp<FakeWindowHandle>& w =
10194 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010195 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010196
10197 touch();
10198
10199 w->assertNoEvents();
10200}
10201
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010202TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010203 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010204 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010205
10206 touch();
10207
10208 mTouchWindow->consumeAnyMotionDown();
10209}
10210
10211TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010212 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010213 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010214 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010215 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010216
10217 touch({PointF{100, 100}});
10218
10219 mTouchWindow->consumeAnyMotionDown();
10220}
10221
10222TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010223 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010224 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010225 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010226
10227 touch();
10228
10229 mTouchWindow->consumeAnyMotionDown();
10230}
10231
10232TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
10233 const sp<FakeWindowHandle>& w =
10234 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010235 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010236
10237 touch();
10238
10239 mTouchWindow->consumeAnyMotionDown();
10240}
10241
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010242TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
10243 const sp<FakeWindowHandle>& w =
10244 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010245 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010246
10247 touch();
10248
10249 w->assertNoEvents();
10250}
10251
10252/**
10253 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
10254 * inside) while letting them pass-through. Note that even though touch passes through the occluding
10255 * window, the occluding window will still receive ACTION_OUTSIDE event.
10256 */
10257TEST_F(InputDispatcherUntrustedTouchesTest,
10258 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
10259 const sp<FakeWindowHandle>& w =
10260 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010261 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010262 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010263
10264 touch();
10265
10266 w->consumeMotionOutside();
10267}
10268
10269TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
10270 const sp<FakeWindowHandle>& w =
10271 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010272 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010273 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010274
10275 touch();
10276
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010277 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010278}
10279
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010280TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010281 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010282 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10283 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010284 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010285
10286 touch();
10287
10288 mTouchWindow->consumeAnyMotionDown();
10289}
10290
10291TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
10292 const sp<FakeWindowHandle>& w =
10293 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10294 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010295 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010296
10297 touch();
10298
10299 mTouchWindow->consumeAnyMotionDown();
10300}
10301
10302TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010303 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010304 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10305 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010306 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010307
10308 touch();
10309
10310 mTouchWindow->assertNoEvents();
10311}
10312
10313TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
10314 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
10315 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010316 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
10317 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010318 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010319 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
10320 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010321 mDispatcher->onWindowInfosChanged(
10322 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010323
10324 touch();
10325
10326 mTouchWindow->assertNoEvents();
10327}
10328
10329TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
10330 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
10331 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010332 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
10333 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010334 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010335 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
10336 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010337 mDispatcher->onWindowInfosChanged(
10338 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010339
10340 touch();
10341
10342 mTouchWindow->consumeAnyMotionDown();
10343}
10344
10345TEST_F(InputDispatcherUntrustedTouchesTest,
10346 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
10347 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010348 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10349 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010350 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010351 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10352 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010353 mDispatcher->onWindowInfosChanged(
10354 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010355
10356 touch();
10357
10358 mTouchWindow->consumeAnyMotionDown();
10359}
10360
10361TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
10362 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010363 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10364 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010365 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010366 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10367 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010368 mDispatcher->onWindowInfosChanged(
10369 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010370
10371 touch();
10372
10373 mTouchWindow->assertNoEvents();
10374}
10375
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010376TEST_F(InputDispatcherUntrustedTouchesTest,
10377 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
10378 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010379 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10380 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010381 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010382 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10383 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010384 mDispatcher->onWindowInfosChanged(
10385 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010386
10387 touch();
10388
10389 mTouchWindow->assertNoEvents();
10390}
10391
10392TEST_F(InputDispatcherUntrustedTouchesTest,
10393 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
10394 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010395 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10396 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010397 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010398 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10399 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010400 mDispatcher->onWindowInfosChanged(
10401 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010402
10403 touch();
10404
10405 mTouchWindow->consumeAnyMotionDown();
10406}
10407
10408TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
10409 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010410 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10411 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010412 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010413
10414 touch();
10415
10416 mTouchWindow->consumeAnyMotionDown();
10417}
10418
10419TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
10420 const sp<FakeWindowHandle>& w =
10421 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010422 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010423
10424 touch();
10425
10426 mTouchWindow->consumeAnyMotionDown();
10427}
10428
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010429TEST_F(InputDispatcherUntrustedTouchesTest,
10430 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
10431 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
10432 const sp<FakeWindowHandle>& w =
10433 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010434 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010435
10436 touch();
10437
10438 mTouchWindow->assertNoEvents();
10439}
10440
10441TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
10442 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
10443 const sp<FakeWindowHandle>& w =
10444 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010445 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010446
10447 touch();
10448
10449 mTouchWindow->consumeAnyMotionDown();
10450}
10451
10452TEST_F(InputDispatcherUntrustedTouchesTest,
10453 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
10454 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
10455 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010456 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10457 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010458 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010459
10460 touch();
10461
10462 mTouchWindow->consumeAnyMotionDown();
10463}
10464
10465TEST_F(InputDispatcherUntrustedTouchesTest,
10466 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
10467 const sp<FakeWindowHandle>& w1 =
10468 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
10469 OPACITY_BELOW_THRESHOLD);
10470 const sp<FakeWindowHandle>& w2 =
10471 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10472 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010473 mDispatcher->onWindowInfosChanged(
10474 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010475
10476 touch();
10477
10478 mTouchWindow->assertNoEvents();
10479}
10480
10481/**
10482 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
10483 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
10484 * (which alone would result in allowing touches) does not affect the blocking behavior.
10485 */
10486TEST_F(InputDispatcherUntrustedTouchesTest,
10487 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
10488 const sp<FakeWindowHandle>& wB =
10489 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
10490 OPACITY_BELOW_THRESHOLD);
10491 const sp<FakeWindowHandle>& wC =
10492 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10493 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010494 mDispatcher->onWindowInfosChanged(
10495 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010496
10497 touch();
10498
10499 mTouchWindow->assertNoEvents();
10500}
10501
10502/**
10503 * This test is testing that a window from a different UID but with same application token doesn't
10504 * block the touch. Apps can share the application token for close UI collaboration for example.
10505 */
10506TEST_F(InputDispatcherUntrustedTouchesTest,
10507 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
10508 const sp<FakeWindowHandle>& w =
10509 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
10510 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010511 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010512
10513 touch();
10514
10515 mTouchWindow->consumeAnyMotionDown();
10516}
10517
arthurhungb89ccb02020-12-30 16:19:01 +080010518class InputDispatcherDragTests : public InputDispatcherTest {
10519protected:
10520 std::shared_ptr<FakeApplicationHandle> mApp;
10521 sp<FakeWindowHandle> mWindow;
10522 sp<FakeWindowHandle> mSecondWindow;
10523 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010524 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010525 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
10526 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +080010527
10528 void SetUp() override {
10529 InputDispatcherTest::SetUp();
10530 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010531 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080010532 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080010533
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010534 mSecondWindow =
10535 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080010536 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080010537
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010538 mSpyWindow =
10539 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010540 mSpyWindow->setSpy(true);
10541 mSpyWindow->setTrustedOverlay(true);
10542 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
10543
arthurhungb89ccb02020-12-30 16:19:01 +080010544 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010545 mDispatcher->onWindowInfosChanged(
10546 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
10547 {},
10548 0,
10549 0});
arthurhungb89ccb02020-12-30 16:19:01 +080010550 }
10551
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010552 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
10553 switch (fromSource) {
10554 case AINPUT_SOURCE_TOUCHSCREEN:
10555 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010556 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010557 ADISPLAY_ID_DEFAULT, {50, 50}))
10558 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10559 break;
10560 case AINPUT_SOURCE_STYLUS:
10561 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010562 injectMotionEvent(*mDispatcher,
10563 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10564 AINPUT_SOURCE_STYLUS)
10565 .buttonState(
10566 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
10567 .pointer(PointerBuilder(0, ToolType::STYLUS)
10568 .x(50)
10569 .y(50))
10570 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010571 break;
10572 case AINPUT_SOURCE_MOUSE:
10573 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010574 injectMotionEvent(*mDispatcher,
10575 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10576 AINPUT_SOURCE_MOUSE)
10577 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
10578 .pointer(PointerBuilder(MOUSE_POINTER_ID,
10579 ToolType::MOUSE)
10580 .x(50)
10581 .y(50))
10582 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010583 break;
10584 default:
10585 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
10586 }
arthurhungb89ccb02020-12-30 16:19:01 +080010587
10588 // Window should receive motion event.
10589 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010590 // Spy window should also receive motion event
10591 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000010592 }
10593
10594 // Start performing drag, we will create a drag window and transfer touch to it.
10595 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
10596 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010597 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +000010598 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010599 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +000010600 }
arthurhungb89ccb02020-12-30 16:19:01 +080010601
10602 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010603 mDragWindow =
10604 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010605 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010606 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
10607 *mWindow->getInfo(), *mSecondWindow->getInfo()},
10608 {},
10609 0,
10610 0});
arthurhungb89ccb02020-12-30 16:19:01 +080010611
10612 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +000010613 bool transferred =
Prabir Pradhan367f3432024-02-13 23:05:58 +000010614 mDispatcher->transferTouchGesture(mWindow->getToken(), mDragWindow->getToken(),
10615 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +000010616 if (transferred) {
10617 mWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +000010618 mDragWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000010619 }
10620 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +080010621 }
10622};
10623
10624TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010625 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +080010626
10627 // Move on window.
10628 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010629 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010630 ADISPLAY_ID_DEFAULT, {50, 50}))
10631 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010632 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080010633 mWindow->consumeDragEvent(false, 50, 50);
10634 mSecondWindow->assertNoEvents();
10635
10636 // Move to another window.
10637 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010638 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010639 ADISPLAY_ID_DEFAULT, {150, 50}))
10640 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010641 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080010642 mWindow->consumeDragEvent(true, 150, 50);
10643 mSecondWindow->consumeDragEvent(false, 50, 50);
10644
10645 // Move back to original window.
10646 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010647 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010648 ADISPLAY_ID_DEFAULT, {50, 50}))
10649 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010650 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080010651 mWindow->consumeDragEvent(false, 50, 50);
10652 mSecondWindow->consumeDragEvent(true, -50, 50);
10653
10654 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010655 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10656 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080010657 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010658 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080010659 mWindow->assertNoEvents();
10660 mSecondWindow->assertNoEvents();
10661}
10662
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010663TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010664 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010665
10666 // No cancel event after drag start
10667 mSpyWindow->assertNoEvents();
10668
10669 const MotionEvent secondFingerDownEvent =
10670 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10671 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010672 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10673 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010674 .build();
10675 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010676 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010677 InputEventInjectionSync::WAIT_FOR_RESULT))
10678 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10679
10680 // Receives cancel for first pointer after next pointer down
10681 mSpyWindow->consumeMotionCancel();
10682 mSpyWindow->consumeMotionDown();
10683
10684 mSpyWindow->assertNoEvents();
10685}
10686
arthurhungf452d0b2021-01-06 00:19:52 +080010687TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010688 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +080010689
10690 // Move on window.
10691 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010692 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +080010693 ADISPLAY_ID_DEFAULT, {50, 50}))
10694 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010695 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080010696 mWindow->consumeDragEvent(false, 50, 50);
10697 mSecondWindow->assertNoEvents();
10698
10699 // Move to another window.
10700 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010701 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +080010702 ADISPLAY_ID_DEFAULT, {150, 50}))
10703 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010704 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080010705 mWindow->consumeDragEvent(true, 150, 50);
10706 mSecondWindow->consumeDragEvent(false, 50, 50);
10707
10708 // drop to another window.
10709 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010710 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +080010711 {150, 50}))
10712 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010713 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010714 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +080010715 mWindow->assertNoEvents();
10716 mSecondWindow->assertNoEvents();
10717}
10718
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010719TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
10720 startDrag();
10721
10722 // No cancel event after drag start
10723 mSpyWindow->assertNoEvents();
10724
10725 const MotionEvent secondFingerDownEvent =
10726 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10727 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10728 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10729 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10730 .build();
10731 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10732 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10733 InputEventInjectionSync::WAIT_FOR_RESULT))
10734 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10735
10736 // Receives cancel for first pointer after next pointer down
10737 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080010738 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010739 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
10740
10741 mSpyWindow->assertNoEvents();
10742
10743 // Spy window calls pilfer pointers
10744 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
10745 mDragWindow->assertNoEvents();
10746
10747 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010748 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010749 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10750 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
10751 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10752 .build();
10753 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010754 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010755 InputEventInjectionSync::WAIT_FOR_RESULT))
10756 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10757
10758 // Drag window should still receive the new event
Prabir Pradhan65455c72024-02-13 21:46:41 +000010759 mDragWindow->consumeMotionEvent(
10760 AllOf(WithMotionAction(ACTION_MOVE), WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010761 mDragWindow->assertNoEvents();
10762}
10763
arthurhung6d4bed92021-03-17 11:59:33 +080010764TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010765 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +080010766
10767 // Move on window and keep button pressed.
10768 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010769 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010770 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10771 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010772 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010773 .build()))
10774 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010775 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080010776 mWindow->consumeDragEvent(false, 50, 50);
10777 mSecondWindow->assertNoEvents();
10778
10779 // Move to another window and release button, expect to drop item.
10780 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010781 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010782 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10783 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010784 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010785 .build()))
10786 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010787 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080010788 mWindow->assertNoEvents();
10789 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010790 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +080010791
10792 // nothing to the window.
10793 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010794 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010795 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
10796 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010797 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010798 .build()))
10799 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010800 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080010801 mWindow->assertNoEvents();
10802 mSecondWindow->assertNoEvents();
10803}
10804
Arthur Hung54745652022-04-20 07:17:41 +000010805TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010806 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +080010807
10808 // Set second window invisible.
10809 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010810 mDispatcher->onWindowInfosChanged(
10811 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +080010812
10813 // Move on window.
10814 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010815 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010816 ADISPLAY_ID_DEFAULT, {50, 50}))
10817 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010818 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010819 mWindow->consumeDragEvent(false, 50, 50);
10820 mSecondWindow->assertNoEvents();
10821
10822 // Move to another window.
10823 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010824 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010825 ADISPLAY_ID_DEFAULT, {150, 50}))
10826 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010827 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010828 mWindow->consumeDragEvent(true, 150, 50);
10829 mSecondWindow->assertNoEvents();
10830
10831 // drop to another window.
10832 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010833 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010834 {150, 50}))
10835 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010836 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010837 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010838 mWindow->assertNoEvents();
10839 mSecondWindow->assertNoEvents();
10840}
10841
Arthur Hung54745652022-04-20 07:17:41 +000010842TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010843 // Ensure window could track pointerIds if it didn't support split touch.
10844 mWindow->setPreventSplitting(true);
10845
Arthur Hung54745652022-04-20 07:17:41 +000010846 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010847 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010848 {50, 50}))
10849 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10850 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10851
10852 const MotionEvent secondFingerDownEvent =
10853 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10854 .displayId(ADISPLAY_ID_DEFAULT)
10855 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010856 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10857 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010858 .build();
10859 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010860 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010861 InputEventInjectionSync::WAIT_FOR_RESULT))
10862 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010863 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +000010864
10865 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010866 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010867}
10868
10869TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
10870 // First down on second window.
10871 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010872 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010873 {150, 50}))
10874 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10875
10876 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10877
10878 // Second down on first window.
10879 const MotionEvent secondFingerDownEvent =
10880 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10881 .displayId(ADISPLAY_ID_DEFAULT)
10882 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010883 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10884 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010885 .build();
10886 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010887 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010888 InputEventInjectionSync::WAIT_FOR_RESULT))
10889 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10890 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +000010891 mSecondWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000010892
10893 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010894 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010895
10896 // Move on window.
10897 const MotionEvent secondFingerMoveEvent =
10898 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10899 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010900 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10901 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010902 .build();
10903 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010904 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010905 InputEventInjectionSync::WAIT_FOR_RESULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +000010906 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000010907 mWindow->consumeDragEvent(false, 50, 50);
10908 mSecondWindow->consumeMotionMove();
10909
10910 // Release the drag pointer should perform drop.
10911 const MotionEvent secondFingerUpEvent =
10912 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10913 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010914 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10915 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010916 .build();
10917 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010918 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010919 InputEventInjectionSync::WAIT_FOR_RESULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +000010920 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010921 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000010922 mWindow->assertNoEvents();
10923 mSecondWindow->consumeMotionMove();
10924}
10925
Arthur Hung3915c1f2022-05-31 07:17:17 +000010926TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010927 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000010928
10929 // Update window of second display.
10930 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010931 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010932 mDispatcher->onWindowInfosChanged(
10933 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10934 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10935 {},
10936 0,
10937 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010938
10939 // Let second display has a touch state.
10940 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010941 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010942 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10943 AINPUT_SOURCE_TOUCHSCREEN)
10944 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010945 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000010946 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000010947 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010948 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010949 mDispatcher->onWindowInfosChanged(
10950 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10951 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10952 {},
10953 0,
10954 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010955
10956 // Move on window.
10957 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010958 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010959 ADISPLAY_ID_DEFAULT, {50, 50}))
10960 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010961 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010962 mWindow->consumeDragEvent(false, 50, 50);
10963 mSecondWindow->assertNoEvents();
10964
10965 // Move to another window.
10966 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010967 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010968 ADISPLAY_ID_DEFAULT, {150, 50}))
10969 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010970 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010971 mWindow->consumeDragEvent(true, 150, 50);
10972 mSecondWindow->consumeDragEvent(false, 50, 50);
10973
10974 // drop to another window.
10975 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010976 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010977 {150, 50}))
10978 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010979 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010980 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000010981 mWindow->assertNoEvents();
10982 mSecondWindow->assertNoEvents();
10983}
10984
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010985TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
10986 startDrag(true, AINPUT_SOURCE_MOUSE);
10987 // Move on window.
10988 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010989 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010990 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10991 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010992 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010993 .x(50)
10994 .y(50))
10995 .build()))
10996 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010997 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010998 mWindow->consumeDragEvent(false, 50, 50);
10999 mSecondWindow->assertNoEvents();
11000
11001 // Move to another window.
11002 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011003 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011004 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
11005 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011006 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011007 .x(150)
11008 .y(50))
11009 .build()))
11010 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000011011 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011012 mWindow->consumeDragEvent(true, 150, 50);
11013 mSecondWindow->consumeDragEvent(false, 50, 50);
11014
11015 // drop to another window.
11016 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011017 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011018 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
11019 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011020 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011021 .x(150)
11022 .y(50))
11023 .build()))
11024 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000011025 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070011026 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011027 mWindow->assertNoEvents();
11028 mSecondWindow->assertNoEvents();
11029}
11030
Linnan Li5af92f92023-07-14 14:36:22 +080011031/**
11032 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
11033 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
11034 */
11035TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
11036 // Down on second window
11037 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11038 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
11039 {150, 50}))
11040 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11041
11042 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
11043 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
11044
11045 // Down on first window
11046 const MotionEvent secondFingerDownEvent =
11047 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11048 .displayId(ADISPLAY_ID_DEFAULT)
11049 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
11050 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
11051 .build();
11052 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11053 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
11054 InputEventInjectionSync::WAIT_FOR_RESULT))
11055 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11056 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
11057 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
11058 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
11059
11060 // Start drag on first window
11061 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
11062
11063 // Trigger cancel
11064 mDispatcher->cancelCurrentTouch();
11065 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
Prabir Pradhan65455c72024-02-13 21:46:41 +000011066 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT,
11067 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE));
Linnan Li5af92f92023-07-14 14:36:22 +080011068 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
11069
11070 ASSERT_TRUE(mDispatcher->waitForIdle());
11071 // The D&D finished with nullptr
11072 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
11073
11074 // Remove drag window
11075 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
11076
11077 // Inject a simple gesture, ensure dispatcher not crashed
11078 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11079 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
11080 PointF{50, 50}))
11081 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11082 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
11083
11084 const MotionEvent moveEvent =
11085 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
11086 .displayId(ADISPLAY_ID_DEFAULT)
11087 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11088 .build();
11089 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11090 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
11091 InputEventInjectionSync::WAIT_FOR_RESULT))
11092 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11093 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
11094
11095 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11096 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
11097 {50, 50}))
11098 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11099 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
11100}
11101
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000011102TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
11103 // Start hovering over the window.
11104 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11105 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
11106 ADISPLAY_ID_DEFAULT, {50, 50}));
11107
11108 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
11109 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
11110
11111 ASSERT_FALSE(startDrag(/*sendDown=*/false))
11112 << "Drag and drop should not work with a hovering pointer";
11113}
11114
Vishnu Nair062a8672021-09-03 16:07:44 -070011115class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
11116
11117TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
11118 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011119 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
11120 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011121 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011122 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
11123 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011124 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011125 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011126 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011127
11128 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000011129 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011130 window->assertNoEvents();
11131
Prabir Pradhan678438e2023-04-13 19:32:51 +000011132 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11133 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070011134 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
11135 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080011136 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070011137 window->assertNoEvents();
11138
11139 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011140 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011141 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011142
Prabir Pradhan678438e2023-04-13 19:32:51 +000011143 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011144 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
11145
Prabir Pradhan678438e2023-04-13 19:32:51 +000011146 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11147 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011148 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11149 window->assertNoEvents();
11150}
11151
11152TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
11153 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
11154 std::make_shared<FakeApplicationHandle>();
11155 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011156 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
11157 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070011158 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011159 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011160 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070011161 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011162 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
11163 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011164 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011165 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070011166 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
11167 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011168 mDispatcher->onWindowInfosChanged(
11169 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011170 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011171 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011172
11173 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000011174 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011175 window->assertNoEvents();
11176
Prabir Pradhan678438e2023-04-13 19:32:51 +000011177 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11178 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070011179 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
11180 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011181 window->assertNoEvents();
11182
11183 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011184 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011185 mDispatcher->onWindowInfosChanged(
11186 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011187
Prabir Pradhan678438e2023-04-13 19:32:51 +000011188 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011189 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
11190
Prabir Pradhan678438e2023-04-13 19:32:51 +000011191 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11192 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011193 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
11194 window->assertNoEvents();
11195}
11196
11197TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
11198 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
11199 std::make_shared<FakeApplicationHandle>();
11200 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011201 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
11202 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070011203 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011204 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011205 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070011206 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011207 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
11208 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011209 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011210 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070011211 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
11212 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011213 mDispatcher->onWindowInfosChanged(
11214 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011215 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011216 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011217
11218 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000011219 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011220 window->assertNoEvents();
11221
Prabir Pradhan678438e2023-04-13 19:32:51 +000011222 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11223 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070011224 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
11225 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011226 window->assertNoEvents();
11227
11228 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011229 mDispatcher->onWindowInfosChanged(
11230 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011231
Prabir Pradhan678438e2023-04-13 19:32:51 +000011232 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011233 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
11234
Prabir Pradhan678438e2023-04-13 19:32:51 +000011235 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11236 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011237 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11238 window->assertNoEvents();
11239}
11240
Antonio Kantekf16f2832021-09-28 04:39:20 +000011241class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
11242protected:
11243 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000011244 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000011245 sp<FakeWindowHandle> mWindow;
11246 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000011247 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000011248
11249 void SetUp() override {
11250 InputDispatcherTest::SetUp();
11251
11252 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000011253 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011254 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011255 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011256 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011257 mSecondWindow =
11258 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011259 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000011260 mThirdWindow =
11261 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
11262 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
11263 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011264
11265 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011266 mDispatcher->onWindowInfosChanged(
11267 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
11268 {},
11269 0,
11270 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000011271 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011272 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011273
Antonio Kantek15beb512022-06-13 22:35:41 +000011274 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000011275 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000011276 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070011277 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
11278 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000011279 mThirdWindow->assertNoEvents();
11280 }
11281
11282 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
11283 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000011284 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000011285 SECOND_DISPLAY_ID)) {
11286 mWindow->assertNoEvents();
11287 mSecondWindow->assertNoEvents();
11288 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070011289 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000011290 }
11291
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011292 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000011293 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070011294 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
11295 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000011296 mWindow->consumeTouchModeEvent(inTouchMode);
11297 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000011298 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000011299 }
11300};
11301
Antonio Kantek26defcf2022-02-08 01:12:27 +000011302TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080011303 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000011304 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
11305 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011306 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011307}
11308
Antonio Kantek26defcf2022-02-08 01:12:27 +000011309TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
11310 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011311 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011312 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011313 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011314 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000011315 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -070011316 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000011317 mWindow->assertNoEvents();
11318 mSecondWindow->assertNoEvents();
11319}
11320
11321TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
11322 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011323 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011324 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011325 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000011326 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000011327 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011328}
11329
Antonio Kantekf16f2832021-09-28 04:39:20 +000011330TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080011331 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000011332 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
11333 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011334 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000011335 mWindow->assertNoEvents();
11336 mSecondWindow->assertNoEvents();
11337}
11338
Antonio Kantek15beb512022-06-13 22:35:41 +000011339TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
11340 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
11341 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
11342 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011343 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000011344 mWindow->assertNoEvents();
11345 mSecondWindow->assertNoEvents();
11346 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
11347}
11348
Antonio Kantek48710e42022-03-24 14:19:30 -070011349TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
11350 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011351 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11352 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070011353 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11354 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
11355
11356 // Then remove focus.
11357 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011358 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070011359
11360 // Assert that caller can switch touch mode by owning one of the last interacted window.
11361 const WindowInfo& windowInfo = *mWindow->getInfo();
11362 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
11363 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011364 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070011365}
11366
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011367class InputDispatcherSpyWindowTest : public InputDispatcherTest {
11368public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011369 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011370 std::shared_ptr<FakeApplicationHandle> application =
11371 std::make_shared<FakeApplicationHandle>();
11372 std::string name = "Fake Spy ";
11373 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011374 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
11375 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011376 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011377 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011378 return spy;
11379 }
11380
11381 sp<FakeWindowHandle> createForeground() {
11382 std::shared_ptr<FakeApplicationHandle> application =
11383 std::make_shared<FakeApplicationHandle>();
11384 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011385 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
11386 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011387 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011388 return window;
11389 }
11390
11391private:
11392 int mSpyCount{0};
11393};
11394
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011395using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011396/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011397 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
11398 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011399TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070011400 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011401 ScopedSilentDeath _silentDeath;
11402
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011403 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011404 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011405 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011406 ".* not a trusted overlay");
11407}
11408
11409/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011410 * Input injection into a display with a spy window but no foreground windows should succeed.
11411 */
11412TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011413 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011414 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011415
11416 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011417 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011418 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11419 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11420}
11421
11422/**
11423 * Verify the order in which different input windows receive events. The touched foreground window
11424 * (if there is one) should always receive the event first. When there are multiple spy windows, the
11425 * spy windows will receive the event according to their Z-order, where the top-most spy window will
11426 * receive events before ones belows it.
11427 *
11428 * Here, we set up a scenario with four windows in the following Z order from the top:
11429 * spy1, spy2, window, spy3.
11430 * We then inject an event and verify that the foreground "window" receives it first, followed by
11431 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
11432 * window.
11433 */
11434TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
11435 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011436 auto spy1 = createSpy();
11437 auto spy2 = createSpy();
11438 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011439 mDispatcher->onWindowInfosChanged(
11440 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011441 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
11442 const size_t numChannels = channels.size();
11443
Michael Wright8e9a8562022-02-09 13:44:29 +000011444 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011445 if (!epollFd.ok()) {
11446 FAIL() << "Failed to create epoll fd";
11447 }
11448
11449 for (size_t i = 0; i < numChannels; i++) {
11450 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
11451 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
11452 FAIL() << "Failed to add fd to epoll";
11453 }
11454 }
11455
11456 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011457 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011458 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11459
11460 std::vector<size_t> eventOrder;
11461 std::vector<struct epoll_event> events(numChannels);
11462 for (;;) {
11463 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
11464 (100ms).count());
11465 if (nFds < 0) {
11466 FAIL() << "Failed to call epoll_wait";
11467 }
11468 if (nFds == 0) {
11469 break; // epoll_wait timed out
11470 }
11471 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070011472 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070011473 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011474 channels[i]->consumeMotionDown();
11475 }
11476 }
11477
11478 // Verify the order in which the events were received.
11479 EXPECT_EQ(3u, eventOrder.size());
11480 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
11481 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
11482 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
11483}
11484
11485/**
11486 * A spy window using the NOT_TOUCHABLE flag does not receive events.
11487 */
11488TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
11489 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011490 auto spy = createSpy();
11491 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011492 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011493
11494 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011495 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011496 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11497 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11498 spy->assertNoEvents();
11499}
11500
11501/**
11502 * A spy window will only receive gestures that originate within its touchable region. Gestures that
11503 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
11504 * to the window.
11505 */
11506TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
11507 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011508 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011509 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011510 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011511
11512 // Inject an event outside the spy window's touchable region.
11513 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011514 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011515 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11516 window->consumeMotionDown();
11517 spy->assertNoEvents();
11518 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011519 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011520 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11521 window->consumeMotionUp();
11522 spy->assertNoEvents();
11523
11524 // Inject an event inside the spy window's touchable region.
11525 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011526 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011527 {5, 10}))
11528 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11529 window->consumeMotionDown();
11530 spy->consumeMotionDown();
11531}
11532
11533/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011534 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011535 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011536 */
11537TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
11538 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011539 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011540 auto spy = createSpy();
11541 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011542 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011543 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011544 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011545
11546 // Inject an event outside the spy window's frame and touchable region.
11547 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011548 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011549 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011550 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11551 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011552 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011553}
11554
11555/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011556 * Even when a spy window spans over multiple foreground windows, the spy should receive all
11557 * pointers that are down within its bounds.
11558 */
11559TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
11560 auto windowLeft = createForeground();
11561 windowLeft->setFrame({0, 0, 100, 200});
11562 auto windowRight = createForeground();
11563 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011564 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011565 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011566 mDispatcher->onWindowInfosChanged(
11567 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011568
11569 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011570 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011571 {50, 50}))
11572 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11573 windowLeft->consumeMotionDown();
11574 spy->consumeMotionDown();
11575
11576 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011577 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011578 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011579 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11580 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011581 .build();
11582 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011583 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011584 InputEventInjectionSync::WAIT_FOR_RESULT))
11585 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11586 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000011587 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011588}
11589
11590/**
11591 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
11592 * the spy should receive the second pointer with ACTION_DOWN.
11593 */
11594TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
11595 auto window = createForeground();
11596 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011597 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011598 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011599 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011600
11601 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011602 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011603 {50, 50}))
11604 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11605 window->consumeMotionDown();
11606 spyRight->assertNoEvents();
11607
11608 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011609 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011610 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011611 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11612 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011613 .build();
11614 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011615 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011616 InputEventInjectionSync::WAIT_FOR_RESULT))
11617 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000011618 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011619 spyRight->consumeMotionDown();
11620}
11621
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011622/**
11623 * The spy window should not be able to affect whether or not touches are split. Only the foreground
11624 * windows should be allowed to control split touch.
11625 */
11626TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080011627 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011628 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011629 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080011630 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011631
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011632 auto window = createForeground();
11633 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011634
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011635 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011636
11637 // First finger down, no window touched.
11638 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011639 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011640 {100, 200}))
11641 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11642 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11643 window->assertNoEvents();
11644
11645 // Second finger down on window, the window should receive touch down.
11646 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011647 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011648 .displayId(ADISPLAY_ID_DEFAULT)
11649 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011650 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11651 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011652 .build();
11653 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011654 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011655 InputEventInjectionSync::WAIT_FOR_RESULT))
11656 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11657
11658 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000011659 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011660}
11661
11662/**
11663 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
11664 * do not receive key events.
11665 */
11666TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011667 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011668 spy->setFocusable(false);
11669
11670 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011671 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011672 setFocusedWindow(window);
11673 window->consumeFocusEvent(true);
11674
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011675 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011676 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11677 window->consumeKeyDown(ADISPLAY_ID_NONE);
11678
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011679 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011680 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11681 window->consumeKeyUp(ADISPLAY_ID_NONE);
11682
11683 spy->assertNoEvents();
11684}
11685
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011686using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
11687
11688/**
11689 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
11690 * are currently sent to any other windows - including other spy windows - will also be cancelled.
11691 */
11692TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
11693 auto window = createForeground();
11694 auto spy1 = createSpy();
11695 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011696 mDispatcher->onWindowInfosChanged(
11697 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011698
11699 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011700 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011701 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11702 window->consumeMotionDown();
11703 spy1->consumeMotionDown();
11704 spy2->consumeMotionDown();
11705
11706 // Pilfer pointers from the second spy window.
11707 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
11708 spy2->assertNoEvents();
11709 spy1->consumeMotionCancel();
11710 window->consumeMotionCancel();
11711
11712 // The rest of the gesture should only be sent to the second spy window.
11713 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011714 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011715 ADISPLAY_ID_DEFAULT))
11716 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11717 spy2->consumeMotionMove();
11718 spy1->assertNoEvents();
11719 window->assertNoEvents();
11720}
11721
11722/**
11723 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
11724 * in the middle of the gesture.
11725 */
11726TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
11727 auto window = createForeground();
11728 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011729 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011730
11731 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011732 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011733 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11734 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11735 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11736
11737 window->releaseChannel();
11738
11739 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11740
11741 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011742 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011743 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11744 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
11745}
11746
11747/**
11748 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
11749 * the spy, but not to any other windows.
11750 */
11751TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
11752 auto spy = createSpy();
11753 auto window = createForeground();
11754
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011755 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011756
11757 // First finger down on the window and the spy.
11758 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011759 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011760 {100, 200}))
11761 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11762 spy->consumeMotionDown();
11763 window->consumeMotionDown();
11764
11765 // Spy window pilfers the pointers.
11766 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11767 window->consumeMotionCancel();
11768
11769 // Second finger down on the window and spy, but the window should not receive the pointer down.
11770 const MotionEvent secondFingerDownEvent =
11771 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11772 .displayId(ADISPLAY_ID_DEFAULT)
11773 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011774 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11775 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011776 .build();
11777 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011778 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011779 InputEventInjectionSync::WAIT_FOR_RESULT))
11780 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11781
Harry Cutts33476232023-01-30 19:57:29 +000011782 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011783
11784 // Third finger goes down outside all windows, so injection should fail.
11785 const MotionEvent thirdFingerDownEvent =
11786 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11787 .displayId(ADISPLAY_ID_DEFAULT)
11788 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011789 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11790 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
11791 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011792 .build();
11793 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011794 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011795 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080011796 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011797
11798 spy->assertNoEvents();
11799 window->assertNoEvents();
11800}
11801
11802/**
11803 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
11804 */
11805TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
11806 auto spy = createSpy();
11807 spy->setFrame(Rect(0, 0, 100, 100));
11808 auto window = createForeground();
11809 window->setFrame(Rect(0, 0, 200, 200));
11810
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011811 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011812
11813 // First finger down on the window only
11814 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011815 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011816 {150, 150}))
11817 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11818 window->consumeMotionDown();
11819
11820 // Second finger down on the spy and window
11821 const MotionEvent secondFingerDownEvent =
11822 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11823 .displayId(ADISPLAY_ID_DEFAULT)
11824 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011825 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11826 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011827 .build();
11828 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011829 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011830 InputEventInjectionSync::WAIT_FOR_RESULT))
11831 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11832 spy->consumeMotionDown();
11833 window->consumeMotionPointerDown(1);
11834
11835 // Third finger down on the spy and window
11836 const MotionEvent thirdFingerDownEvent =
11837 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11838 .displayId(ADISPLAY_ID_DEFAULT)
11839 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011840 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11841 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
11842 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011843 .build();
11844 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011845 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011846 InputEventInjectionSync::WAIT_FOR_RESULT))
11847 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11848 spy->consumeMotionPointerDown(1);
11849 window->consumeMotionPointerDown(2);
11850
11851 // Spy window pilfers the pointers.
11852 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000011853 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
11854 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011855
11856 spy->assertNoEvents();
11857 window->assertNoEvents();
11858}
11859
11860/**
11861 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
11862 * other windows should be canceled. If this results in the cancellation of all pointers for some
11863 * window, then that window should receive ACTION_CANCEL.
11864 */
11865TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
11866 auto spy = createSpy();
11867 spy->setFrame(Rect(0, 0, 100, 100));
11868 auto window = createForeground();
11869 window->setFrame(Rect(0, 0, 200, 200));
11870
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011871 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011872
11873 // First finger down on both spy and window
11874 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011875 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011876 {10, 10}))
11877 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11878 window->consumeMotionDown();
11879 spy->consumeMotionDown();
11880
11881 // Second finger down on the spy and window
11882 const MotionEvent secondFingerDownEvent =
11883 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11884 .displayId(ADISPLAY_ID_DEFAULT)
11885 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011886 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11887 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011888 .build();
11889 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011890 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011891 InputEventInjectionSync::WAIT_FOR_RESULT))
11892 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11893 spy->consumeMotionPointerDown(1);
11894 window->consumeMotionPointerDown(1);
11895
11896 // Spy window pilfers the pointers.
11897 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11898 window->consumeMotionCancel();
11899
11900 spy->assertNoEvents();
11901 window->assertNoEvents();
11902}
11903
11904/**
11905 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
11906 * be sent to other windows
11907 */
11908TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
11909 auto spy = createSpy();
11910 spy->setFrame(Rect(0, 0, 100, 100));
11911 auto window = createForeground();
11912 window->setFrame(Rect(0, 0, 200, 200));
11913
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011914 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011915
11916 // First finger down on both window and spy
11917 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011918 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011919 {10, 10}))
11920 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11921 window->consumeMotionDown();
11922 spy->consumeMotionDown();
11923
11924 // Spy window pilfers the pointers.
11925 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11926 window->consumeMotionCancel();
11927
11928 // Second finger down on the window only
11929 const MotionEvent secondFingerDownEvent =
11930 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11931 .displayId(ADISPLAY_ID_DEFAULT)
11932 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011933 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11934 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011935 .build();
11936 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011937 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011938 InputEventInjectionSync::WAIT_FOR_RESULT))
11939 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11940 window->consumeMotionDown();
11941 window->assertNoEvents();
11942
11943 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
11944 spy->consumeMotionMove();
11945 spy->assertNoEvents();
11946}
11947
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011948/**
11949 * A window on the left and a window on the right. Also, a spy window that's above all of the
11950 * windows, and spanning both left and right windows.
11951 * Send simultaneous motion streams from two different devices, one to the left window, and another
11952 * to the right window.
11953 * Pilfer from spy window.
11954 * Check that the pilfering only affects the pointers that are actually being received by the spy.
11955 */
11956TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
11957 sp<FakeWindowHandle> spy = createSpy();
11958 spy->setFrame(Rect(0, 0, 200, 200));
11959 sp<FakeWindowHandle> leftWindow = createForeground();
11960 leftWindow->setFrame(Rect(0, 0, 100, 100));
11961
11962 sp<FakeWindowHandle> rightWindow = createForeground();
11963 rightWindow->setFrame(Rect(100, 0, 200, 100));
11964
11965 constexpr int32_t stylusDeviceId = 1;
11966 constexpr int32_t touchDeviceId = 2;
11967
11968 mDispatcher->onWindowInfosChanged(
11969 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
11970
11971 // Stylus down on left window and spy
11972 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
11973 .deviceId(stylusDeviceId)
11974 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
11975 .build());
11976 leftWindow->consumeMotionEvent(
11977 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11978 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11979
11980 // Finger down on right window and spy - but spy already has stylus
11981 mDispatcher->notifyMotion(
11982 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11983 .deviceId(touchDeviceId)
11984 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
11985 .build());
11986 rightWindow->consumeMotionEvent(
11987 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011988 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011989
11990 // Act: pilfer from spy. Spy is currently receiving touch events.
11991 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011992 leftWindow->consumeMotionEvent(
11993 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011994 rightWindow->consumeMotionEvent(
11995 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
11996
11997 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
11998 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
11999 .deviceId(stylusDeviceId)
12000 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
12001 .build());
12002 mDispatcher->notifyMotion(
12003 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
12004 .deviceId(touchDeviceId)
12005 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
12006 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070012007 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070012008
12009 spy->assertNoEvents();
12010 leftWindow->assertNoEvents();
12011 rightWindow->assertNoEvents();
12012}
12013
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000012014TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
12015 auto window = createForeground();
12016 auto spy = createSpy();
12017 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
12018
12019 mDispatcher->notifyMotion(
12020 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
12021 .deviceId(1)
12022 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
12023 .build());
12024 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12025 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12026
12027 // Pilfer pointers from the spy window should fail.
12028 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
12029 spy->assertNoEvents();
12030 window->assertNoEvents();
12031}
12032
Prabir Pradhand65552b2021-10-07 11:23:50 -070012033class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
12034public:
12035 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
12036 std::shared_ptr<FakeApplicationHandle> overlayApplication =
12037 std::make_shared<FakeApplicationHandle>();
12038 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012039 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
12040 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070012041 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012042 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012043 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012044 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070012045 overlay->setTrustedOverlay(true);
12046
12047 std::shared_ptr<FakeApplicationHandle> application =
12048 std::make_shared<FakeApplicationHandle>();
12049 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012050 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
12051 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070012052 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012053 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070012054
12055 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012056 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070012057 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000012058 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070012059 return {std::move(overlay), std::move(window)};
12060 }
12061
12062 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000012063 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070012064 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000012065 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070012066 }
12067
12068 void sendStylusEvent(int32_t action) {
12069 NotifyMotionArgs motionArgs =
12070 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
12071 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012072 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000012073 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070012074 }
12075};
12076
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012077using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
12078
12079TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070012080 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012081 ScopedSilentDeath _silentDeath;
12082
Prabir Pradhand65552b2021-10-07 11:23:50 -070012083 auto [overlay, window] = setupStylusOverlayScenario();
12084 overlay->setTrustedOverlay(false);
12085 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012086 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
12087 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070012088 ".* not a trusted overlay");
12089}
12090
12091TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
12092 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012093 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070012094
12095 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
12096 overlay->consumeMotionDown();
12097 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
12098 overlay->consumeMotionUp();
12099
12100 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
12101 window->consumeMotionDown();
12102 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
12103 window->consumeMotionUp();
12104
12105 overlay->assertNoEvents();
12106 window->assertNoEvents();
12107}
12108
12109TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
12110 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012111 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012112 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070012113
12114 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
12115 overlay->consumeMotionDown();
12116 window->consumeMotionDown();
12117 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
12118 overlay->consumeMotionUp();
12119 window->consumeMotionUp();
12120
12121 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
12122 window->consumeMotionDown();
12123 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
12124 window->consumeMotionUp();
12125
12126 overlay->assertNoEvents();
12127 window->assertNoEvents();
12128}
12129
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000012130/**
12131 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
12132 * The scenario is as follows:
12133 * - The stylus interceptor overlay is configured as a spy window.
12134 * - The stylus interceptor spy receives the start of a new stylus gesture.
12135 * - It pilfers pointers and then configures itself to no longer be a spy.
12136 * - The stylus interceptor continues to receive the rest of the gesture.
12137 */
12138TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
12139 auto [overlay, window] = setupStylusOverlayScenario();
12140 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012141 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000012142
12143 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
12144 overlay->consumeMotionDown();
12145 window->consumeMotionDown();
12146
12147 // The interceptor pilfers the pointers.
12148 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
12149 window->consumeMotionCancel();
12150
12151 // The interceptor configures itself so that it is no longer a spy.
12152 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012153 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000012154
12155 // It continues to receive the rest of the stylus gesture.
12156 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
12157 overlay->consumeMotionMove();
12158 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
12159 overlay->consumeMotionUp();
12160
12161 window->assertNoEvents();
12162}
12163
Prabir Pradhan5735a322022-04-11 17:23:34 +000012164struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012165 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000012166 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000012167 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
12168 std::unique_ptr<InputDispatcher>& mDispatcher;
12169
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012170 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000012171 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
12172
12173 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012174 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000012175 ADISPLAY_ID_DEFAULT, {100, 200},
12176 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
12177 AMOTION_EVENT_INVALID_CURSOR_POSITION},
12178 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
12179 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
12180 }
12181
12182 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012183 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000012184 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000012185 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000012186 mPolicyFlags);
12187 }
12188
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012189 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000012190 std::shared_ptr<FakeApplicationHandle> overlayApplication =
12191 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012192 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
12193 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000012194 window->setOwnerInfo(mPid, mUid);
12195 return window;
12196 }
12197};
12198
12199using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
12200
12201TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012202 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012203 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012204 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012205
12206 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12207 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12208 window->consumeMotionDown();
12209
12210 setFocusedWindow(window);
12211 window->consumeFocusEvent(true);
12212
12213 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12214 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
12215 window->consumeKeyDown(ADISPLAY_ID_NONE);
12216}
12217
12218TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012219 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012220 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012221 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012222
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012223 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012224 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
12225 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12226
12227 setFocusedWindow(window);
12228 window->consumeFocusEvent(true);
12229
12230 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
12231 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
12232 window->assertNoEvents();
12233}
12234
12235TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012236 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012237 auto window = owner.createWindow("Owned window");
12238 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012239 spy->setSpy(true);
12240 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012241 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012242
12243 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12244 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12245 spy->consumeMotionDown();
12246 window->consumeMotionDown();
12247}
12248
12249TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012250 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012251 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012252
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012253 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012254 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012255 randosSpy->setSpy(true);
12256 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012257 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012258
12259 // The event is targeted at owner's window, so injection should succeed, but the spy should
12260 // not receive the event.
12261 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12262 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12263 randosSpy->assertNoEvents();
12264 window->consumeMotionDown();
12265}
12266
12267TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012268 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012269 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012270
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012271 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012272 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012273 randosSpy->setSpy(true);
12274 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012275 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012276
12277 // A user that has injection permission can inject into any window.
12278 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012279 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000012280 ADISPLAY_ID_DEFAULT));
12281 randosSpy->consumeMotionDown();
12282 window->consumeMotionDown();
12283
12284 setFocusedWindow(randosSpy);
12285 randosSpy->consumeFocusEvent(true);
12286
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012287 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000012288 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
12289 window->assertNoEvents();
12290}
12291
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012292TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012293 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012294 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012295
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012296 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012297 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012298 randosWindow->setFrame(Rect{-10, -10, -5, -5});
12299 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012300 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012301
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012302 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000012303 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12304 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12305 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012306 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000012307}
12308
Prabir Pradhan64f21d22023-11-28 21:19:42 +000012309using InputDispatcherPointerInWindowTest = InputDispatcherTest;
12310
12311TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
12312 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12313
12314 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12315 ADISPLAY_ID_DEFAULT);
12316 left->setFrame(Rect(0, 0, 100, 100));
12317 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12318 "Right Window", ADISPLAY_ID_DEFAULT);
12319 right->setFrame(Rect(100, 0, 200, 100));
12320 sp<FakeWindowHandle> spy =
12321 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
12322 spy->setFrame(Rect(0, 0, 200, 100));
12323 spy->setTrustedOverlay(true);
12324 spy->setSpy(true);
12325
12326 mDispatcher->onWindowInfosChanged(
12327 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
12328
12329 // Hover into the left window.
12330 mDispatcher->notifyMotion(
12331 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
12332 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
12333 .build());
12334
12335 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12336 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12337
12338 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12339 /*pointerId=*/0));
12340 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12341 /*pointerId=*/0));
12342 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12343 /*pointerId=*/0));
12344
12345 // Hover move to the right window.
12346 mDispatcher->notifyMotion(
12347 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
12348 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
12349 .build());
12350
12351 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12352 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12353 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
12354
12355 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12356 /*pointerId=*/0));
12357 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12358 /*pointerId=*/0));
12359 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12360 /*pointerId=*/0));
12361
12362 // Stop hovering.
12363 mDispatcher->notifyMotion(
12364 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
12365 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
12366 .build());
12367
12368 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12369 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12370
12371 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12372 /*pointerId=*/0));
12373 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12374 /*pointerId=*/0));
12375 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12376 /*pointerId=*/0));
12377}
12378
12379TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
12380 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12381
12382 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12383 ADISPLAY_ID_DEFAULT);
12384 left->setFrame(Rect(0, 0, 100, 100));
12385 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12386 "Right Window", ADISPLAY_ID_DEFAULT);
12387 right->setFrame(Rect(100, 0, 200, 100));
12388 sp<FakeWindowHandle> spy =
12389 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
12390 spy->setFrame(Rect(0, 0, 200, 100));
12391 spy->setTrustedOverlay(true);
12392 spy->setSpy(true);
12393
12394 mDispatcher->onWindowInfosChanged(
12395 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
12396
12397 // First pointer down on left window.
12398 mDispatcher->notifyMotion(
12399 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12400 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12401 .build());
12402
12403 left->consumeMotionDown();
12404 spy->consumeMotionDown();
12405
12406 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12407 /*pointerId=*/0));
12408 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12409 /*pointerId=*/0));
12410 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12411 /*pointerId=*/0));
12412
12413 // Second pointer down on right window.
12414 mDispatcher->notifyMotion(
12415 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12416 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12417 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
12418 .build());
12419
12420 left->consumeMotionMove();
12421 right->consumeMotionDown();
12422 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
12423
12424 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12425 /*pointerId=*/0));
12426 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12427 /*pointerId=*/0));
12428 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12429 /*pointerId=*/0));
12430 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12431 /*pointerId=*/1));
12432 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12433 /*pointerId=*/1));
12434 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12435 /*pointerId=*/1));
12436
12437 // Second pointer up.
12438 mDispatcher->notifyMotion(
12439 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
12440 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12441 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
12442 .build());
12443
12444 left->consumeMotionMove();
12445 right->consumeMotionUp();
12446 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
12447
12448 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12449 /*pointerId=*/0));
12450 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12451 /*pointerId=*/0));
12452 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12453 /*pointerId=*/0));
12454 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12455 /*pointerId=*/1));
12456 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12457 /*pointerId=*/1));
12458 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12459 /*pointerId=*/1));
12460
12461 // First pointer up.
12462 mDispatcher->notifyMotion(
12463 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
12464 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12465 .build());
12466
12467 left->consumeMotionUp();
12468 spy->consumeMotionUp();
12469
12470 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12471 /*pointerId=*/0));
12472 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12473 /*pointerId=*/0));
12474 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12475 /*pointerId=*/0));
12476}
12477
12478TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
12479 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12480
12481 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12482 ADISPLAY_ID_DEFAULT);
12483 left->setFrame(Rect(0, 0, 100, 100));
12484 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12485 "Right Window", ADISPLAY_ID_DEFAULT);
12486 right->setFrame(Rect(100, 0, 200, 100));
12487
12488 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
12489
12490 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12491 /*pointerId=*/0));
12492 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12493 /*pointerId=*/0));
12494
12495 // Hover move into the window.
12496 mDispatcher->notifyMotion(
12497 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12498 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
12499 .rawXCursorPosition(50)
12500 .rawYCursorPosition(50)
12501 .deviceId(DEVICE_ID)
12502 .build());
12503
12504 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12505
12506 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12507 /*pointerId=*/0));
12508
12509 // Move the mouse with another device. This cancels the hovering pointer from the first device.
12510 mDispatcher->notifyMotion(
12511 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12512 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
12513 .rawXCursorPosition(51)
12514 .rawYCursorPosition(50)
12515 .deviceId(SECOND_DEVICE_ID)
12516 .build());
12517
12518 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12519 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12520
12521 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
12522 // a HOVER_EXIT from the first device.
12523 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12524 /*pointerId=*/0));
12525 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
12526 SECOND_DEVICE_ID,
12527 /*pointerId=*/0));
12528
12529 // Move the mouse outside the window. Document the current behavior, where the window does not
12530 // receive HOVER_EXIT even though the mouse left the window.
12531 mDispatcher->notifyMotion(
12532 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12533 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
12534 .rawXCursorPosition(150)
12535 .rawYCursorPosition(50)
12536 .deviceId(SECOND_DEVICE_ID)
12537 .build());
12538
12539 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12540 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12541 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12542 /*pointerId=*/0));
12543 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
12544 SECOND_DEVICE_ID,
12545 /*pointerId=*/0));
12546}
12547
Garfield Tane84e6f92019-08-29 17:28:41 -070012548} // namespace android::inputdispatcher