blob: 60d598ff8046f05be4f15e4a90bad3272baf97f5 [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000018#include "../BlockingQueue.h"
Siarhei Vishniakou2defec02023-06-08 17:24:44 -070019#include "FakeApplicationHandle.h"
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +000020#include "FakeInputTracingBackend.h"
Prabir Pradhane3b28dd2023-10-06 04:19:29 +000021#include "TestEventMatchers.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080022
Cody Heiner166a5af2023-07-07 12:25:00 -070023#include <NotifyArgsBuilders.h>
Prabir Pradhan5893d362023-11-17 04:30:40 +000024#include <android-base/logging.h>
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070025#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080026#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080027#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070028#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070029#include <binder/Binder.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000030#include <com_android_input_flags.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000031#include <fcntl.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000032#include <flag_macros.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080033#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080034#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100035#include <input/Input.h>
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070036#include <input/PrintTools.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080037#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080038#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100039
Garfield Tan1c7bc862020-01-28 13:24:04 -080040#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080041#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070042#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080043#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080044#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080045
Garfield Tan1c7bc862020-01-28 13:24:04 -080046using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050047using android::gui::FocusRequest;
48using android::gui::TouchOcclusionMode;
49using android::gui::WindowInfo;
50using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080051using android::os::InputEventInjectionResult;
52using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080053
Garfield Tane84e6f92019-08-29 17:28:41 -070054namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080055
Dominik Laskowski2f01d772022-03-23 16:01:29 -070056using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080057using testing::AllOf;
Prabir Pradhan5893d362023-11-17 04:30:40 +000058using testing::Not;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070059
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070060namespace {
61
Michael Wrightd02c5b62014-02-10 15:10:22 -080062// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000063static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080064
65// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000066static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080067static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080068
Jeff Brownf086ddb2014-02-11 14:28:48 -080069// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000070static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
71static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080072
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000073// Ensure common actions are interchangeable between keys and motions for convenience.
74static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
75static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080076static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
77static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
78static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
79static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070080static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080081static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070082static constexpr int32_t ACTION_SCROLL = AMOTION_EVENT_ACTION_SCROLL;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080083static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080084static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080085/**
86 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
87 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
88 * index 0) is the new pointer going down. The same pointer could have been placed at a different
89 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
90 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
91 * pointer id=0 leaves but the pointer id=1 remains.
92 */
93static constexpr int32_t POINTER_0_DOWN =
94 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080095static constexpr int32_t POINTER_1_DOWN =
96 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000097static constexpr int32_t POINTER_2_DOWN =
98 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000099static constexpr int32_t POINTER_3_DOWN =
100 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +0000101static constexpr int32_t POINTER_0_UP =
102 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800103static constexpr int32_t POINTER_1_UP =
104 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +0000105static constexpr int32_t POINTER_2_UP =
106 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800107
Antonio Kantek15beb512022-06-13 22:35:41 +0000108// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000109static constexpr gui::Pid WINDOW_PID{999};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000110static constexpr gui::Uid WINDOW_UID{1001};
Prabir Pradhan5735a322022-04-11 17:23:34 +0000111
Antonio Kantek15beb512022-06-13 22:35:41 +0000112// The default pid and uid for the windows created on the secondary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000113static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000114static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000115
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000116// An arbitrary pid of the gesture monitor window
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000117static constexpr gui::Pid MONITOR_PID{2001};
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000118
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700119/**
120 * If we expect to receive the event, the timeout can be made very long. When the test are running
121 * correctly, we will actually never wait until the end of the timeout because the wait will end
122 * when the event comes in. Still, this value shouldn't be infinite. During development, a local
123 * change may cause the test to fail. This timeout should be short enough to not annoy so that the
124 * developer can see the failure quickly (on human scale).
125 */
126static constexpr std::chrono::duration CONSUME_TIMEOUT_EVENT_EXPECTED = 1000ms;
127/**
128 * When no event is expected, we can have a very short timeout. A large value here would slow down
129 * the tests. In the unlikely event of system being too slow, the event may still be present but the
130 * timeout would complete before it is consumed. This would result in test flakiness. If this
131 * occurs, the flakiness rate would be high. Since the flakes are treated with high priority, this
132 * would get noticed and addressed quickly.
133 */
134static constexpr std::chrono::duration CONSUME_TIMEOUT_NO_EVENT_EXPECTED = 10ms;
135
Arthur Hungc539dbb2022-12-08 07:45:36 +0000136static constexpr int expectedWallpaperFlags =
137 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
138
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800139using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
140
Gang Wang342c9272020-01-13 13:15:04 -0500141/**
142 * Return a DOWN key event with KEYCODE_A.
143 */
144static KeyEvent getTestKeyEvent() {
145 KeyEvent event;
146
Garfield Tanfbe732e2020-01-24 11:26:14 -0800147 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
148 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
149 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500150 return event;
151}
152
Michael Wrightd02c5b62014-02-10 15:10:22 -0800153// --- FakeInputDispatcherPolicy ---
154
155class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000156 struct AnrResult {
157 sp<IBinder> token{};
Prabir Pradhanfc364722024-02-08 17:51:20 +0000158 std::optional<gui::Pid> pid{};
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000159 };
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800160 /* Stores data about a user-activity-poke event from the dispatcher. */
161 struct UserActivityPokeEvent {
162 nsecs_t eventTime;
163 int32_t eventType;
164 int32_t displayId;
165
166 bool operator==(const UserActivityPokeEvent& rhs) const = default;
167
168 friend std::ostream& operator<<(std::ostream& os, const UserActivityPokeEvent& ev) {
169 os << "UserActivityPokeEvent[time=" << ev.eventTime << ", eventType=" << ev.eventType
170 << ", displayId=" << ev.displayId << "]";
171 return os;
172 }
173 };
Prabir Pradhanedd96402022-02-15 01:46:16 -0800174
Michael Wrightd02c5b62014-02-10 15:10:22 -0800175public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000176 FakeInputDispatcherPolicy() = default;
177 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800178
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800179 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700180 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700181 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700182 EXPECT_EQ(event.getDisplayId(), args.displayId);
183
184 const auto& keyEvent = static_cast<const KeyEvent&>(event);
185 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
186 EXPECT_EQ(keyEvent.getAction(), args.action);
187 });
Jackal Guof9696682018-10-05 12:23:23 +0800188 }
189
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700190 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
191 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700192 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700193 EXPECT_EQ(event.getDisplayId(), args.displayId);
194
195 const auto& motionEvent = static_cast<const MotionEvent&>(event);
196 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
197 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000198 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
199 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
200 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
201 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700202 });
Jackal Guof9696682018-10-05 12:23:23 +0800203 }
204
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700205 void assertFilterInputEventWasNotCalled() {
206 std::scoped_lock lock(mLock);
207 ASSERT_EQ(nullptr, mFilteredEvent);
208 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800209
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800210 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700211 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800212 ASSERT_TRUE(mConfigurationChangedTime)
213 << "Timed out waiting for configuration changed call";
214 ASSERT_EQ(*mConfigurationChangedTime, when);
215 mConfigurationChangedTime = std::nullopt;
216 }
217
218 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700219 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800220 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800221 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800222 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
223 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
224 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
225 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
226 mLastNotifySwitch = std::nullopt;
227 }
228
chaviwfd6d3512019-03-25 13:23:49 -0700229 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700230 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800231 ASSERT_EQ(touchedToken, mOnPointerDownToken);
232 mOnPointerDownToken.clear();
233 }
234
235 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700236 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800237 ASSERT_TRUE(mOnPointerDownToken == nullptr)
238 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700239 }
240
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700241 // This function must be called soon after the expected ANR timer starts,
242 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500243 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700244 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500245 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800246 std::unique_lock lock(mLock);
247 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500248 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800249 ASSERT_NO_FATAL_FAILURE(
250 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500251 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700252 }
253
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000254 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800255 const sp<WindowInfoHandle>& window) {
256 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
257 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
258 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500259 }
260
Prabir Pradhanedd96402022-02-15 01:46:16 -0800261 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
262 const sp<IBinder>& expectedToken,
Prabir Pradhanfc364722024-02-08 17:51:20 +0000263 std::optional<gui::Pid> expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800264 std::unique_lock lock(mLock);
265 android::base::ScopedLockAssertion assumeLocked(mLock);
266 AnrResult result;
267 ASSERT_NO_FATAL_FAILURE(result =
268 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000269 ASSERT_EQ(expectedToken, result.token);
270 ASSERT_EQ(expectedPid, result.pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500271 }
272
Prabir Pradhanedd96402022-02-15 01:46:16 -0800273 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000274 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500275 std::unique_lock lock(mLock);
276 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800277 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
278 const auto& [token, _] = result;
279 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000280 }
281
Prabir Pradhanedd96402022-02-15 01:46:16 -0800282 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
Prabir Pradhanfc364722024-02-08 17:51:20 +0000283 std::optional<gui::Pid> expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800284 std::unique_lock lock(mLock);
285 android::base::ScopedLockAssertion assumeLocked(mLock);
286 AnrResult result;
287 ASSERT_NO_FATAL_FAILURE(
288 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000289 ASSERT_EQ(expectedToken, result.token);
290 ASSERT_EQ(expectedPid, result.pid);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800291 }
292
293 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000294 sp<IBinder> getResponsiveWindowToken() {
295 std::unique_lock lock(mLock);
296 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800297 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
298 const auto& [token, _] = result;
299 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700300 }
301
302 void assertNotifyAnrWasNotCalled() {
303 std::scoped_lock lock(mLock);
304 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800305 ASSERT_TRUE(mAnrWindows.empty());
306 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500307 << "ANR was not called, but please also consume the 'connection is responsive' "
308 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700309 }
310
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000311 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800312 std::unique_lock lock(mLock);
313 base::ScopedLockAssertion assumeLocked(mLock);
314
315 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
316 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000317 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800318 enabled;
319 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000320 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
321 << ") to be called.";
322 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800323 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000324 auto request = *mPointerCaptureRequest;
325 mPointerCaptureRequest.reset();
326 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800327 }
328
329 void assertSetPointerCaptureNotCalled() {
330 std::unique_lock lock(mLock);
331 base::ScopedLockAssertion assumeLocked(mLock);
332
333 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000334 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800335 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000336 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800337 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000338 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800339 }
340
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -0700341 void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
342 const sp<IBinder>& targetToken) {
343 dispatcher.waitForIdle();
arthurhungf452d0b2021-01-06 00:19:52 +0800344 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800345 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800346 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800347 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800348 }
349
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800350 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
351 std::unique_lock lock(mLock);
352 base::ScopedLockAssertion assumeLocked(mLock);
353 std::optional<sp<IBinder>> receivedToken =
354 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
355 mNotifyInputChannelBroken);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000356 ASSERT_TRUE(receivedToken.has_value()) << "Did not receive the broken channel token";
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800357 ASSERT_EQ(token, *receivedToken);
358 }
359
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800360 /**
361 * Set policy timeout. A value of zero means next key will not be intercepted.
362 */
363 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
364 mInterceptKeyTimeout = timeout;
365 }
366
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -0800367 std::chrono::nanoseconds getKeyWaitingForEventsTimeout() override { return 500ms; }
368
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700369 void setStaleEventTimeout(std::chrono::nanoseconds timeout) { mStaleEventTimeout = timeout; }
370
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800371 void assertUserActivityNotPoked() {
372 std::unique_lock lock(mLock);
373 base::ScopedLockAssertion assumeLocked(mLock);
374
375 std::optional<UserActivityPokeEvent> pokeEvent =
376 getItemFromStorageLockedInterruptible(500ms, mUserActivityPokeEvents, lock,
377 mNotifyUserActivity);
378
379 ASSERT_FALSE(pokeEvent) << "Expected user activity not to have been poked";
Josep del Riob3981622023-04-18 15:49:45 +0000380 }
381
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800382 /**
383 * Asserts that a user activity poke has happened. The earliest recorded poke event will be
384 * cleared after this call.
385 *
386 * If an expected UserActivityPokeEvent is provided, asserts that the given event is the
387 * earliest recorded poke event.
388 */
389 void assertUserActivityPoked(std::optional<UserActivityPokeEvent> expectedPokeEvent = {}) {
390 std::unique_lock lock(mLock);
391 base::ScopedLockAssertion assumeLocked(mLock);
392
393 std::optional<UserActivityPokeEvent> pokeEvent =
394 getItemFromStorageLockedInterruptible(500ms, mUserActivityPokeEvents, lock,
395 mNotifyUserActivity);
396 ASSERT_TRUE(pokeEvent) << "Expected a user poke event";
397
398 if (expectedPokeEvent) {
399 ASSERT_EQ(expectedPokeEvent, *pokeEvent);
400 }
Josep del Riob3981622023-04-18 15:49:45 +0000401 }
402
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000403 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000404 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
405 }
406
407 void assertNotifyDeviceInteractionWasNotCalled() {
408 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
409 }
410
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000411 void setUnhandledKeyHandler(std::function<std::optional<KeyEvent>(const KeyEvent&)> handler) {
412 std::scoped_lock lock(mLock);
413 mUnhandledKeyHandler = handler;
414 }
415
416 void assertUnhandledKeyReported(int32_t keycode) {
417 std::unique_lock lock(mLock);
418 base::ScopedLockAssertion assumeLocked(mLock);
419 std::optional<int32_t> unhandledKeycode =
420 getItemFromStorageLockedInterruptible(100ms, mReportedUnhandledKeycodes, lock,
421 mNotifyUnhandledKey);
422 ASSERT_TRUE(unhandledKeycode) << "Expected unhandled key to be reported";
423 ASSERT_EQ(unhandledKeycode, keycode);
424 }
425
426 void assertUnhandledKeyNotReported() {
427 std::unique_lock lock(mLock);
428 base::ScopedLockAssertion assumeLocked(mLock);
429 std::optional<int32_t> unhandledKeycode =
430 getItemFromStorageLockedInterruptible(10ms, mReportedUnhandledKeycodes, lock,
431 mNotifyUnhandledKey);
432 ASSERT_FALSE(unhandledKeycode) << "Expected unhandled key NOT to be reported";
433 }
434
Michael Wrightd02c5b62014-02-10 15:10:22 -0800435private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700436 std::mutex mLock;
437 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
438 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
439 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
440 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800441
Prabir Pradhan99987712020-11-10 18:43:05 -0800442 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000443
444 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800445
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700446 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700447 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800448 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
449 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700450 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800451 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
452 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700453
arthurhungf452d0b2021-01-06 00:19:52 +0800454 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800455 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800456
457 std::condition_variable mNotifyUserActivity;
458 std::queue<UserActivityPokeEvent> mUserActivityPokeEvents;
arthurhungf452d0b2021-01-06 00:19:52 +0800459
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800460 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
461
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700462 std::chrono::nanoseconds mStaleEventTimeout = 1000ms;
463
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000464 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000465
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000466 std::condition_variable mNotifyUnhandledKey;
467 std::queue<int32_t> mReportedUnhandledKeycodes GUARDED_BY(mLock);
468 std::function<std::optional<KeyEvent>(const KeyEvent&)> mUnhandledKeyHandler GUARDED_BY(mLock);
469
Prabir Pradhanedd96402022-02-15 01:46:16 -0800470 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
471 // for a specific container to become non-empty. When the container is non-empty, return the
472 // first entry from the container and erase it.
473 template <class T>
474 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
475 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
476 // If there is an ANR, Dispatcher won't be idle because there are still events
477 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
478 // before checking if ANR was called.
479 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
480 // to provide it some time to act. 100ms seems reasonable.
481 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
482 const std::chrono::time_point start = std::chrono::steady_clock::now();
483 std::optional<T> token =
484 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
485 if (!token.has_value()) {
486 ADD_FAILURE() << "Did not receive the ANR callback";
487 return {};
488 }
489
490 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
491 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
492 // the dispatcher started counting before this function was called
493 if (std::chrono::abs(timeout - waited) > 100ms) {
494 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
495 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
496 << "ms, but waited "
497 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
498 << "ms instead";
499 }
500 return *token;
501 }
502
503 template <class T>
504 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
505 std::queue<T>& storage,
506 std::unique_lock<std::mutex>& lock,
507 std::condition_variable& condition)
508 REQUIRES(mLock) {
509 condition.wait_for(lock, timeout,
510 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
511 if (storage.empty()) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800512 return std::nullopt;
513 }
514 T item = storage.front();
515 storage.pop();
516 return std::make_optional(item);
517 }
518
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600519 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700520 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800521 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800522 }
523
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000524 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800525 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700526 std::scoped_lock lock(mLock);
Prabir Pradhanfc364722024-02-08 17:51:20 +0000527 mAnrWindows.push({connectionToken, pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700528 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500529 }
530
Prabir Pradhanedd96402022-02-15 01:46:16 -0800531 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000532 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500533 std::scoped_lock lock(mLock);
Prabir Pradhanfc364722024-02-08 17:51:20 +0000534 mResponsiveWindows.push({connectionToken, pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500535 mNotifyAnr.notify_all();
536 }
537
538 void notifyNoFocusedWindowAnr(
539 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
540 std::scoped_lock lock(mLock);
541 mAnrApplications.push(applicationHandle);
542 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800543 }
544
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800545 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
546 std::scoped_lock lock(mLock);
547 mBrokenInputChannels.push(connectionToken);
548 mNotifyInputChannelBroken.notify_all();
549 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800550
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600551 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700552
Chris Yef59a2f42020-10-16 12:55:26 -0700553 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
554 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
555 const std::vector<float>& values) override {}
556
557 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
558 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000559
Chris Yefb552902021-02-03 17:18:37 -0800560 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
561
Prabir Pradhana41d2442023-04-20 21:30:40 +0000562 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700563 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000564 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700565 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000566 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
567 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800568 break;
569 }
570
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700571 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000572 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
573 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800574 break;
575 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700576 default: {
577 ADD_FAILURE() << "Should only filter keys or motions";
578 break;
579 }
Jackal Guof9696682018-10-05 12:23:23 +0800580 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800581 return true;
582 }
583
Prabir Pradhana41d2442023-04-20 21:30:40 +0000584 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
585 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800586 // Clear intercept state when we handled the event.
587 mInterceptKeyTimeout = 0ms;
588 }
589 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800590
Yeabkal Wubshit88a90412023-12-21 18:23:04 -0800591 void interceptMotionBeforeQueueing(int32_t, uint32_t, int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800592
Prabir Pradhana41d2442023-04-20 21:30:40 +0000593 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800594 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
595 // Clear intercept state so we could dispatch the event in next wake.
596 mInterceptKeyTimeout = 0ms;
597 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800598 }
599
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000600 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent& event,
Prabir Pradhana41d2442023-04-20 21:30:40 +0000601 uint32_t) override {
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000602 std::scoped_lock lock(mLock);
603 mReportedUnhandledKeycodes.emplace(event.getKeyCode());
604 mNotifyUnhandledKey.notify_all();
605 return mUnhandledKeyHandler != nullptr ? mUnhandledKeyHandler(event) : std::nullopt;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800606 }
607
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600608 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
609 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700610 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800611 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
612 * essentially a passthrough for notifySwitch.
613 */
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000614 mLastNotifySwitch =
615 NotifySwitchArgs(InputEvent::nextId(), when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800616 }
617
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800618 void pokeUserActivity(nsecs_t eventTime, int32_t eventType, int32_t displayId) override {
Josep del Riob3981622023-04-18 15:49:45 +0000619 std::scoped_lock lock(mLock);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800620 mNotifyUserActivity.notify_all();
621 mUserActivityPokeEvents.push({eventTime, eventType, displayId});
Josep del Riob3981622023-04-18 15:49:45 +0000622 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800623
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700624 bool isStaleEvent(nsecs_t currentTime, nsecs_t eventTime) override {
625 return std::chrono::nanoseconds(currentTime - eventTime) >= mStaleEventTimeout;
626 }
627
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600628 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700629 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700630 mOnPointerDownToken = newToken;
631 }
632
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000633 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800634 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000635 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800636 mPointerCaptureChangedCondition.notify_all();
637 }
638
arthurhungf452d0b2021-01-06 00:19:52 +0800639 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
640 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800641 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800642 mDropTargetWindowToken = token;
643 }
644
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000645 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000646 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000647 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
648 }
649
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700650 void assertFilterInputEventWasCalledInternal(
651 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700652 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800653 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700654 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800655 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800656 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800657};
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700658} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800659
Michael Wrightd02c5b62014-02-10 15:10:22 -0800660// --- InputDispatcherTest ---
661
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000662// The trace is a global variable for now, to avoid having to pass it into all of the
663// FakeWindowHandles created throughout the tests.
664// TODO(b/210460522): Update the tests to avoid the need to have the trace be a global variable.
665static std::shared_ptr<VerifyingTrace> gVerifyingTrace = std::make_shared<VerifyingTrace>();
666
Michael Wrightd02c5b62014-02-10 15:10:22 -0800667class InputDispatcherTest : public testing::Test {
668protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000669 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700670 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800671
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000672 void SetUp() override {
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000673 gVerifyingTrace->reset();
Prabir Pradhana41d2442023-04-20 21:30:40 +0000674 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000675 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy,
676 std::make_unique<FakeInputTracingBackend>(
677 gVerifyingTrace));
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700678
Harry Cutts101ee9b2023-07-06 18:04:14 +0000679 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000680 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700681 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800682 }
683
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000684 void TearDown() override {
Prabir Pradhan0eaf1402024-02-05 22:43:04 +0000685 ASSERT_NO_FATAL_FAILURE(gVerifyingTrace->verifyExpectedEventsTraced());
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700686 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000687 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700688 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800689 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700690
691 /**
692 * Used for debugging when writing the test
693 */
694 void dumpDispatcherState() {
695 std::string dump;
696 mDispatcher->dump(dump);
697 std::stringstream ss(dump);
698 std::string to;
699
700 while (std::getline(ss, to, '\n')) {
701 ALOGE("%s", to.c_str());
702 }
703 }
Vishnu Nair958da932020-08-21 17:12:37 -0700704
Chavi Weingarten847e8512023-03-29 00:26:09 +0000705 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700706 FocusRequest request;
707 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000708 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700709 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
710 request.displayId = window->getInfo()->displayId;
711 mDispatcher->setFocusedWindow(request);
712 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800713};
714
Michael Wrightd02c5b62014-02-10 15:10:22 -0800715TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
716 KeyEvent event;
717
718 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800719 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
720 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000721 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600722 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800723 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000724 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000725 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800726 << "Should reject key events with undefined action.";
727
728 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800729 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
730 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600731 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800732 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000733 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000734 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800735 << "Should reject key events with ACTION_MULTIPLE.";
736}
737
738TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
739 MotionEvent event;
740 PointerProperties pointerProperties[MAX_POINTERS + 1];
741 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800742 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800743 pointerProperties[i].clear();
744 pointerProperties[i].id = i;
745 pointerCoords[i].clear();
746 }
747
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800748 // Some constants commonly used below
749 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
750 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
751 constexpr int32_t metaState = AMETA_NONE;
752 constexpr MotionClassification classification = MotionClassification::NONE;
753
chaviw9eaa22c2020-07-01 16:21:27 -0700754 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800755 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800756 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000757 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700758 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700759 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
760 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000761 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800762 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000763 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000764 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800765 << "Should reject motion events with undefined action.";
766
767 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800768 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800769 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
770 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
771 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
772 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000773 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800774 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000775 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000776 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800777 << "Should reject motion events with pointer down index too large.";
778
Garfield Tanfbe732e2020-01-24 11:26:14 -0800779 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700780 AMOTION_EVENT_ACTION_POINTER_DOWN |
781 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700782 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
783 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700784 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000785 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800786 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000787 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000788 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800789 << "Should reject motion events with pointer down index too small.";
790
791 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800792 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800793 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
794 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
795 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
796 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000797 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800798 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000799 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000800 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800801 << "Should reject motion events with pointer up index too large.";
802
Garfield Tanfbe732e2020-01-24 11:26:14 -0800803 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700804 AMOTION_EVENT_ACTION_POINTER_UP |
805 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700806 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
807 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700808 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000809 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800810 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000811 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000812 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800813 << "Should reject motion events with pointer up index too small.";
814
815 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800816 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
817 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700818 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700819 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
820 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000821 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800822 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000823 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000824 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800825 << "Should reject motion events with 0 pointers.";
826
Garfield Tanfbe732e2020-01-24 11:26:14 -0800827 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
828 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700829 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700830 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
831 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000832 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800833 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000834 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000835 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800836 << "Should reject motion events with more than MAX_POINTERS pointers.";
837
838 // Rejects motion events with invalid pointer ids.
839 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800840 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
841 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700842 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700843 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
844 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000845 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800846 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000847 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000848 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800849 << "Should reject motion events with pointer ids less than 0.";
850
851 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800852 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
853 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700854 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700855 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
856 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000857 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800858 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000859 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000860 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800861 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
862
863 // Rejects motion events with duplicate pointer ids.
864 pointerProperties[0].id = 1;
865 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800866 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
867 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700868 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700869 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
870 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000871 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800872 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000873 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000874 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800875 << "Should reject motion events with duplicate pointer ids.";
876}
877
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800878/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
879
880TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
881 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000882 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800883 ASSERT_TRUE(mDispatcher->waitForIdle());
884
885 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
886}
887
888TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000889 NotifySwitchArgs args(InputEvent::nextId(), /*eventTime=*/20, /*policyFlags=*/0,
890 /*switchValues=*/1,
Harry Cutts33476232023-01-30 19:57:29 +0000891 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000892 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800893
894 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
895 args.policyFlags |= POLICY_FLAG_TRUSTED;
896 mFakePolicy->assertNotifySwitchWasCalled(args);
897}
898
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700899namespace {
900
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700901static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700902// Default input dispatching timeout if there is no focused application or paused window
903// from which to determine an appropriate dispatching timeout.
904static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
905 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
906 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800907
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800908class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800909public:
Garfield Tan15601662020-09-22 15:32:38 -0700910 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700911 : mConsumer(std::move(clientChannel)), mName(name) {}
chaviwd1c23182019-12-20 18:44:56 -0800912
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800913 std::unique_ptr<InputEvent> consume(std::chrono::milliseconds timeout, bool handled = false) {
914 auto [consumeSeq, event] = receiveEvent(timeout);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700915 if (!consumeSeq) {
916 return nullptr;
917 }
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000918 finishEvent(*consumeSeq, handled);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800919 return std::move(event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700920 }
921
922 /**
923 * Receive an event without acknowledging it.
924 * Return the sequence number that could later be used to send finished signal.
925 */
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800926 std::pair<std::optional<uint32_t>, std::unique_ptr<InputEvent>> receiveEvent(
927 std::chrono::milliseconds timeout) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800928 uint32_t consumeSeq;
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800929 std::unique_ptr<InputEvent> event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800930
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800931 std::chrono::time_point start = std::chrono::steady_clock::now();
932 status_t status = WOULD_BLOCK;
933 while (status == WOULD_BLOCK) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800934 InputEvent* rawEventPtr = nullptr;
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700935 status = mConsumer.consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800936 &rawEventPtr);
937 event = std::unique_ptr<InputEvent>(rawEventPtr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800938 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700939 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800940 break;
941 }
942 }
943
944 if (status == WOULD_BLOCK) {
945 // Just means there's no event available.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800946 return std::make_pair(std::nullopt, nullptr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800947 }
948
949 if (status != OK) {
950 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800951 return std::make_pair(std::nullopt, nullptr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800952 }
953 if (event == nullptr) {
954 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800955 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800956 return std::make_pair(consumeSeq, std::move(event));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700957 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800958
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700959 /**
960 * To be used together with "receiveEvent" to complete the consumption of an event.
961 */
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000962 void finishEvent(uint32_t consumeSeq, bool handled = true) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700963 const status_t status = mConsumer.sendFinishedSignal(consumeSeq, handled);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700964 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800965 }
966
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000967 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700968 const status_t status = mConsumer.sendTimeline(inputEventId, timeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000969 ASSERT_EQ(OK, status);
970 }
971
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700972 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000973 std::optional<int32_t> expectedDisplayId,
974 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800975 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800976
977 ASSERT_NE(nullptr, event) << mName.c_str()
978 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800979 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700980 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
981 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800982
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000983 if (expectedDisplayId.has_value()) {
984 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
985 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800986
Tiger Huang8664f8c2018-10-11 19:14:35 +0800987 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700988 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800989 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700990 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000991 if (expectedFlags.has_value()) {
992 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
993 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800994 break;
995 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700996 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800997 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700998 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000999 if (expectedFlags.has_value()) {
1000 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
1001 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001002 break;
1003 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001004 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001005 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
1006 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001007 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -08001008 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
1009 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001010 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001011 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
1012 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001013 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +08001014 FAIL() << "Use 'consumeDragEvent' for DRAG events";
1015 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001016 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001017 }
1018
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001019 std::unique_ptr<MotionEvent> consumeMotion() {
1020 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001021
1022 if (event == nullptr) {
1023 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
1024 return nullptr;
1025 }
1026
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001027 if (event->getType() != InputEventType::MOTION) {
1028 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001029 return nullptr;
1030 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001031 return std::unique_ptr<MotionEvent>(static_cast<MotionEvent*>(event.release()));
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001032 }
1033
1034 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001035 std::unique_ptr<MotionEvent> motionEvent = consumeMotion();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001036 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1037 ASSERT_THAT(*motionEvent, matcher);
1038 }
1039
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001040 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001041 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001042 ASSERT_NE(nullptr, event) << mName.c_str()
1043 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001044 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1045 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001046
1047 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1048 << mName.c_str() << ": event displayId should always be NONE.";
1049
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001050 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1051 EXPECT_EQ(hasFocus, focusEvent.getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001052 }
1053
Prabir Pradhan99987712020-11-10 18:43:05 -08001054 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001055 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -08001056 ASSERT_NE(nullptr, event) << mName.c_str()
1057 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001058 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1059 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001060
1061 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1062 << mName.c_str() << ": event displayId should always be NONE.";
1063
1064 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1065 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1066 }
1067
arthurhungb89ccb02020-12-30 16:19:01 +08001068 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001069 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +08001070 ASSERT_NE(nullptr, event) << mName.c_str()
1071 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001072 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001073
1074 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1075 << mName.c_str() << ": event displayId should always be NONE.";
1076
1077 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1078 EXPECT_EQ(isExiting, dragEvent.isExiting());
1079 EXPECT_EQ(x, dragEvent.getX());
1080 EXPECT_EQ(y, dragEvent.getY());
1081 }
1082
Antonio Kantekf16f2832021-09-28 04:39:20 +00001083 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001084 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +00001085 ASSERT_NE(nullptr, event) << mName.c_str()
1086 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001087 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1088 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001089
1090 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1091 << mName.c_str() << ": event displayId should always be NONE.";
1092 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1093 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1094 }
1095
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001096 void assertNoEvents(std::chrono::milliseconds timeout) {
1097 std::unique_ptr<InputEvent> event = consume(timeout);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001098 if (event == nullptr) {
1099 return;
1100 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001101 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001102 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001103 ADD_FAILURE() << "Received key event " << keyEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001104 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001105 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001106 ADD_FAILURE() << "Received motion event " << motionEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001107 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001108 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1109 ADD_FAILURE() << "Received focus event, hasFocus = "
1110 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001111 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001112 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1113 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1114 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001115 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001116 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1117 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1118 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001119 }
1120 FAIL() << mName.c_str()
1121 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001122 }
1123
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001124 sp<IBinder> getToken() { return mConsumer.getChannel()->getConnectionToken(); }
chaviwd1c23182019-12-20 18:44:56 -08001125
Siarhei Vishniakou8d660132024-01-11 16:48:44 -08001126 int getChannelFd() { return mConsumer.getChannel()->getFd(); }
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001127
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001128private:
1129 InputConsumer mConsumer;
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001130 DynamicInputEventFactory mEventFactory;
chaviwd1c23182019-12-20 18:44:56 -08001131
1132 std::string mName;
1133};
1134
chaviw3277faf2021-05-19 16:45:23 -05001135class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001136public:
1137 static const int32_t WIDTH = 600;
1138 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001139
Chris Yea209fde2020-07-22 13:54:51 -07001140 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001141 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001142 int32_t displayId, bool createInputChannel = true)
chaviwd1c23182019-12-20 18:44:56 -08001143 : mName(name) {
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001144 sp<IBinder> token;
1145 if (createInputChannel) {
Garfield Tan15601662020-09-22 15:32:38 -07001146 base::Result<std::unique_ptr<InputChannel>> channel =
1147 dispatcher->createInputChannel(name);
1148 token = (*channel)->getConnectionToken();
1149 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001150 }
1151
1152 inputApplicationHandle->updateInfo();
1153 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1154
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001155 mInfo.token = token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001156 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001157 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001158 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001159 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001160 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001161 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001162 mInfo.globalScaleFactor = 1.0;
1163 mInfo.touchableRegion.clear();
1164 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001165 mInfo.ownerPid = WINDOW_PID;
1166 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001167 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001168 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001169 }
1170
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001171 sp<FakeWindowHandle> clone(int32_t displayId) {
1172 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1173 handle->mInfo = mInfo;
1174 handle->mInfo.displayId = displayId;
1175 handle->mInfo.id = sId++;
1176 handle->mInputReceiver = mInputReceiver;
1177 return handle;
1178 }
1179
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001180 void setTouchable(bool touchable) {
1181 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1182 }
chaviwd1c23182019-12-20 18:44:56 -08001183
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001184 void setFocusable(bool focusable) {
1185 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1186 }
1187
1188 void setVisible(bool visible) {
1189 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1190 }
Vishnu Nair958da932020-08-21 17:12:37 -07001191
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001192 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001193 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001194 }
1195
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001196 void setPaused(bool paused) {
1197 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1198 }
1199
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001200 void setPreventSplitting(bool preventSplitting) {
1201 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001202 }
1203
1204 void setSlippery(bool slippery) {
1205 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1206 }
1207
1208 void setWatchOutsideTouch(bool watchOutside) {
1209 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1210 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001211
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001212 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1213
1214 void setInterceptsStylus(bool interceptsStylus) {
1215 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1216 }
1217
1218 void setDropInput(bool dropInput) {
1219 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1220 }
1221
1222 void setDropInputIfObscured(bool dropInputIfObscured) {
1223 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1224 }
1225
1226 void setNoInputChannel(bool noInputChannel) {
1227 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1228 }
1229
Josep del Riob3981622023-04-18 15:49:45 +00001230 void setDisableUserActivity(bool disableUserActivity) {
1231 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1232 }
1233
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07001234 void setGlobalStylusBlocksTouch(bool shouldGlobalStylusBlockTouch) {
1235 mInfo.setInputConfig(WindowInfo::InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH,
1236 shouldGlobalStylusBlockTouch);
1237 }
1238
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001239 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1240
chaviw3277faf2021-05-19 16:45:23 -05001241 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001242
Bernardo Rufino7393d172021-02-26 13:56:11 +00001243 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1244
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001245 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001246 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001247 mInfo.touchableRegion.clear();
1248 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001249
1250 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1251 ui::Transform translate;
1252 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1253 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001254 }
1255
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001256 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1257
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001258 void setIsWallpaper(bool isWallpaper) {
1259 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1260 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001261
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001262 void setDupTouchToWallpaper(bool hasWallpaper) {
1263 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1264 }
chaviwd1c23182019-12-20 18:44:56 -08001265
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001266 void setTrustedOverlay(bool trustedOverlay) {
1267 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1268 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001269
chaviw9eaa22c2020-07-01 16:21:27 -07001270 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1271 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1272 }
1273
1274 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001275
yunho.shinf4a80b82020-11-16 21:13:57 +09001276 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1277
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001278 std::unique_ptr<KeyEvent> consumeKey(bool handled = true) {
1279 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED, handled);
1280 if (event == nullptr) {
1281 ADD_FAILURE() << "No event";
1282 return nullptr;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001283 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001284 if (event->getType() != InputEventType::KEY) {
1285 ADD_FAILURE() << "Instead of key event, got " << event;
1286 return nullptr;
1287 }
1288 return std::unique_ptr<KeyEvent>(static_cast<KeyEvent*>(event.release()));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001289 }
1290
1291 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001292 std::unique_ptr<KeyEvent> keyEvent = consumeKey();
1293 ASSERT_NE(nullptr, keyEvent);
1294 ASSERT_THAT(*keyEvent, matcher);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001295 }
1296
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001297 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001298 consumeKeyEvent(AllOf(WithKeyAction(ACTION_DOWN), WithDisplayId(expectedDisplayId),
1299 WithFlags(expectedFlags)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001300 }
1301
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001302 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001303 consumeKeyEvent(AllOf(WithKeyAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1304 WithFlags(expectedFlags)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001305 }
1306
Svet Ganov5d3bc372020-01-26 23:11:07 -08001307 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001308 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001309 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1310 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001311 }
1312
1313 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001314 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001315 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1316 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001317 }
1318
1319 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001320 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001321 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1322 }
1323
1324 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1325 std::optional<int32_t> expectedFlags = std::nullopt) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001326 consumeMotionEvent(
1327 AllOf(WithMotionAction(ACTION_DOWN),
1328 testing::Conditional(expectedDisplayId.has_value(),
1329 WithDisplayId(*expectedDisplayId), testing::_),
1330 testing::Conditional(expectedFlags.has_value(), WithFlags(*expectedFlags),
1331 testing::_)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001332 }
1333
Svet Ganov5d3bc372020-01-26 23:11:07 -08001334 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001335 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1336 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001337 const int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001338 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001339 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1340 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001341 }
1342
1343 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001344 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001345 const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001346 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001347 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1348 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001349 }
1350
1351 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001352 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001353 consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1354 WithFlags(expectedFlags)));
Michael Wright3a240c42019-12-10 20:53:41 +00001355 }
1356
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001357 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1358 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001359 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE),
1360 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001361 }
1362
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001363 void consumeMotionOutsideWithZeroedCoords() {
1364 consumeMotionEvent(
1365 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE), WithRawCoords(0, 0)));
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001366 }
1367
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001368 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1369 ASSERT_NE(mInputReceiver, nullptr)
1370 << "Cannot consume events from a window with no receiver";
1371 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1372 }
1373
Prabir Pradhan99987712020-11-10 18:43:05 -08001374 void consumeCaptureEvent(bool hasCapture) {
1375 ASSERT_NE(mInputReceiver, nullptr)
1376 << "Cannot consume events from a window with no receiver";
1377 mInputReceiver->consumeCaptureEvent(hasCapture);
1378 }
1379
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001380 std::unique_ptr<MotionEvent> consumeMotionEvent(
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001381 const ::testing::Matcher<MotionEvent>& matcher = testing::_) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001382 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
1383 if (event == nullptr) {
1384 ADD_FAILURE() << "No event";
1385 return nullptr;
Prabir Pradhan5893d362023-11-17 04:30:40 +00001386 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001387 if (event->getType() != InputEventType::MOTION) {
1388 ADD_FAILURE() << "Instead of motion event, got " << *event;
1389 return nullptr;
1390 }
1391 std::unique_ptr<MotionEvent> motionEvent =
1392 std::unique_ptr<MotionEvent>(static_cast<MotionEvent*>(event.release()));
1393 EXPECT_THAT(*motionEvent, matcher);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001394 return motionEvent;
chaviwd1c23182019-12-20 18:44:56 -08001395 }
1396
arthurhungb89ccb02020-12-30 16:19:01 +08001397 void consumeDragEvent(bool isExiting, float x, float y) {
1398 mInputReceiver->consumeDragEvent(isExiting, x, y);
1399 }
1400
Antonio Kantekf16f2832021-09-28 04:39:20 +00001401 void consumeTouchModeEvent(bool inTouchMode) {
1402 ASSERT_NE(mInputReceiver, nullptr)
1403 << "Cannot consume events from a window with no receiver";
1404 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1405 }
1406
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001407 std::pair<std::optional<uint32_t>, std::unique_ptr<InputEvent>> receiveEvent() {
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001408 return receive();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001409 }
1410
1411 void finishEvent(uint32_t sequenceNum) {
1412 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1413 mInputReceiver->finishEvent(sequenceNum);
1414 }
1415
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001416 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1417 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1418 mInputReceiver->sendTimeline(inputEventId, timeline);
1419 }
1420
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001421 void assertNoEvents(std::chrono::milliseconds timeout = CONSUME_TIMEOUT_NO_EVENT_EXPECTED) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001422 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001423 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001424 return; // Can't receive events if the window does not have input channel
1425 }
1426 ASSERT_NE(nullptr, mInputReceiver)
1427 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001428 mInputReceiver->assertNoEvents(timeout);
Arthur Hungb92218b2018-08-14 12:00:21 +08001429 }
1430
chaviwaf87b3e2019-10-01 16:59:28 -07001431 sp<IBinder> getToken() { return mInfo.token; }
1432
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001433 const std::string& getName() { return mName; }
1434
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001435 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001436 mInfo.ownerPid = ownerPid;
1437 mInfo.ownerUid = ownerUid;
1438 }
1439
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001440 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001441
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001442 void destroyReceiver() { mInputReceiver = nullptr; }
1443
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001444 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1445
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001446 // FakeWindowHandle uses this consume method to ensure received events are added to the trace.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001447 std::unique_ptr<InputEvent> consume(std::chrono::milliseconds timeout, bool handled = true) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001448 if (mInputReceiver == nullptr) {
1449 LOG(FATAL) << "Cannot consume event from a window with no input event receiver";
1450 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001451 std::unique_ptr<InputEvent> event = mInputReceiver->consume(timeout, handled);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001452 if (event == nullptr) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001453 ADD_FAILURE() << "Consume failed: no event";
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001454 }
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001455 expectReceivedEventTraced(event);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001456 return event;
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001457 }
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001458
1459private:
1460 FakeWindowHandle(std::string name) : mName(name){};
1461 const std::string mName;
1462 std::shared_ptr<FakeInputReceiver> mInputReceiver;
1463 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
1464 friend class sp<FakeWindowHandle>;
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001465
1466 // FakeWindowHandle uses this receive method to ensure received events are added to the trace.
1467 std::pair<std::optional<uint32_t /*seq*/>, std::unique_ptr<InputEvent>> receive() {
1468 if (mInputReceiver == nullptr) {
1469 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1470 return std::make_pair(std::nullopt, nullptr);
1471 }
1472 auto out = mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1473 const auto& [_, event] = out;
1474 expectReceivedEventTraced(event);
1475 return std::move(out);
1476 }
1477
1478 void expectReceivedEventTraced(const std::unique_ptr<InputEvent>& event) {
1479 if (!event) {
1480 return;
1481 }
1482
1483 switch (event->getType()) {
1484 case InputEventType::KEY: {
Prabir Pradhan4497c862023-12-15 07:13:30 +00001485 gVerifyingTrace->expectKeyDispatchTraced(static_cast<KeyEvent&>(*event), mInfo.id);
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001486 break;
1487 }
1488 case InputEventType::MOTION: {
Prabir Pradhan4497c862023-12-15 07:13:30 +00001489 gVerifyingTrace->expectMotionDispatchTraced(static_cast<MotionEvent&>(*event),
1490 mInfo.id);
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001491 break;
1492 }
1493 default:
1494 break;
1495 }
1496 }
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001497};
1498
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001499std::atomic<int32_t> FakeWindowHandle::sId{1};
1500
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001501class FakeMonitorReceiver {
1502public:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001503 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId)
1504 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001505
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001506 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001507
1508 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001509 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1510 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001511 }
1512
1513 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001514 const auto [sequenceNum, _] = mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1515 return sequenceNum;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001516 }
1517
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001518 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001519
1520 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001521 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1522 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001523 }
1524
1525 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001526 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1527 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001528 }
1529
1530 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001531 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1532 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001533 }
1534
1535 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001536 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001537 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1538 WithDisplayId(expectedDisplayId),
1539 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1540 }
1541
1542 void consumeMotionPointerDown(int32_t pointerIdx) {
1543 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1544 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001545 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1546 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001547 }
1548
1549 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001550 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001551 }
1552
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001553 std::unique_ptr<MotionEvent> consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001554
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001555 void assertNoEvents() { mInputReceiver.assertNoEvents(CONSUME_TIMEOUT_NO_EVENT_EXPECTED); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001556
1557private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001558 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001559};
1560
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001561static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001562 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001563 int32_t displayId = ADISPLAY_ID_NONE,
1564 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001565 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001566 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001567 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001568 KeyEvent event;
1569 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1570
1571 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001572 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001573 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1574 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001575
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001576 if (!allowKeyRepeat) {
1577 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1578 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001579 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001580 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001581}
1582
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001583static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1584 InputEventInjectionResult result =
1585 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1586 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1587 if (result != InputEventInjectionResult::TIMED_OUT) {
1588 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1589 }
1590}
1591
1592static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001593 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001594 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001595}
1596
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001597// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1598// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1599// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001600static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1601 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001602 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001603 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001604 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001605}
1606
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001607static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001608 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001609 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001610}
1611
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001612static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001613 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001614 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001615 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001616 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001617 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1618 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001619}
1620
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001621static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001622 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1623 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001624 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001625 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1626 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001627 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001628 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001629 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001630 MotionEventBuilder motionBuilder =
1631 MotionEventBuilder(action, source)
1632 .displayId(displayId)
1633 .eventTime(eventTime)
1634 .rawXCursorPosition(cursorPosition.x)
1635 .rawYCursorPosition(cursorPosition.y)
1636 .pointer(
1637 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1638 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1639 motionBuilder.downTime(eventTime);
1640 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001641
1642 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001643 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1644 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001645}
1646
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001647static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1648 int32_t displayId,
1649 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001650 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001651}
1652
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001653static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1654 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001655 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001656 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001657}
1658
Jackal Guof9696682018-10-05 12:23:23 +08001659static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1660 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1661 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001662 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1663 AINPUT_SOURCE_KEYBOARD, displayId, POLICY_FLAG_PASS_TO_USER, action,
1664 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001665
1666 return args;
1667}
1668
Josep del Riob3981622023-04-18 15:49:45 +00001669static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1670 int32_t displayId = ADISPLAY_ID_NONE) {
1671 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1672 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001673 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1674 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C,
1675 AMETA_META_ON, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001676
1677 return args;
1678}
1679
1680static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1681 int32_t displayId = ADISPLAY_ID_NONE) {
1682 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1683 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001684 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1685 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST,
1686 KEY_ASSISTANT, AMETA_NONE, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001687
1688 return args;
1689}
1690
Prabir Pradhan678438e2023-04-13 19:32:51 +00001691[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1692 int32_t displayId,
1693 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001694 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001695 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1696 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1697 }
1698
chaviwd1c23182019-12-20 18:44:56 -08001699 PointerProperties pointerProperties[pointerCount];
1700 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001701
chaviwd1c23182019-12-20 18:44:56 -08001702 for (size_t i = 0; i < pointerCount; i++) {
1703 pointerProperties[i].clear();
1704 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001705 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001706
chaviwd1c23182019-12-20 18:44:56 -08001707 pointerCoords[i].clear();
1708 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1709 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1710 }
Jackal Guof9696682018-10-05 12:23:23 +08001711
1712 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1713 // Define a valid motion event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001714 NotifyMotionArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, source,
1715 displayId, POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0,
1716 /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001717 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001718 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001719 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001720 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001721
1722 return args;
1723}
1724
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001725static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1726 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1727}
1728
chaviwd1c23182019-12-20 18:44:56 -08001729static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1730 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1731}
1732
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001733static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1734 const PointerCaptureRequest& request) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001735 return NotifyPointerCaptureChangedArgs(InputEvent::nextId(), systemTime(SYSTEM_TIME_MONOTONIC),
1736 request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001737}
1738
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001739} // namespace
1740
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001741/**
1742 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1743 * broken channel.
1744 */
1745TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1746 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1747 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001748 sp<FakeWindowHandle>::make(application, mDispatcher,
1749 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001750
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001751 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001752
1753 // Window closes its channel, but the window remains.
1754 window->destroyReceiver();
1755 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1756}
1757
Arthur Hungb92218b2018-08-14 12:00:21 +08001758TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001759 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001760 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1761 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001762
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001763 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001764 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001765 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001766 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001767
1768 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001769 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001770}
1771
Siarhei Vishniakouaeed0da2024-01-09 08:57:13 -08001772using InputDispatcherDeathTest = InputDispatcherTest;
1773
1774/**
1775 * When 'onWindowInfosChanged' arguments contain a duplicate entry for the same window, dispatcher
1776 * should crash.
1777 */
1778TEST_F(InputDispatcherDeathTest, DuplicateWindowInfosAbortDispatcher) {
1779 testing::GTEST_FLAG(death_test_style) = "threadsafe";
1780 ScopedSilentDeath _silentDeath;
1781
1782 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1783 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1784 "Fake Window", ADISPLAY_ID_DEFAULT);
1785 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
1786 {{*window->getInfo(), *window->getInfo()}, {}, 0, 0}),
1787 "Incorrect WindowInfosUpdate provided");
1788}
1789
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001790TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1791 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001792 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1793 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001794
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001795 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001796 // Inject a MotionEvent to an unknown display.
1797 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001798 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001799 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1800
1801 // Window should receive motion event.
1802 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1803}
1804
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001805/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001806 * Calling onWindowInfosChanged once should not cause any issues.
1807 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001808 * called twice.
1809 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001810TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001811 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001812 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1813 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001814 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001815
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001816 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001817 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001818 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001819 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001820 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001821
1822 // Window should receive motion event.
1823 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1824}
1825
1826/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001827 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001828 */
1829TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001830 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001831 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1832 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001833 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001834
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001835 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1836 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001837 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001838 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001839 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001840 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001841
1842 // Window should receive motion event.
1843 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1844}
1845
Arthur Hungb92218b2018-08-14 12:00:21 +08001846// The foreground window should receive the first touch down event.
1847TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001848 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001849 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001850 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001851 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001852 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001853
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001854 mDispatcher->onWindowInfosChanged(
1855 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001856 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001857 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001858 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001859
1860 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001861 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001862 windowSecond->assertNoEvents();
1863}
1864
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001865/**
1866 * Two windows: A top window, and a wallpaper behind the window.
1867 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1868 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001869 * 1. foregroundWindow <-- dup touch to wallpaper
1870 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001871 */
1872TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1873 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1874 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001875 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001876 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001877 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001878 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001879 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001880
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001881 mDispatcher->onWindowInfosChanged(
1882 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001883 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001884 injectMotionEvent(*mDispatcher,
1885 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1886 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
1887 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001888 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1889
1890 // Both foreground window and its wallpaper should receive the touch down
1891 foregroundWindow->consumeMotionDown();
1892 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1893
1894 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001895 injectMotionEvent(*mDispatcher,
1896 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1897 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
1898 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001899 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1900
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001901 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001902 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1903
1904 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001905 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001906 foregroundWindow->consumeMotionCancel();
1907 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1908 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1909}
1910
1911/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001912 * Two fingers down on the window, and lift off the first finger.
1913 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1914 * contains a single pointer.
1915 */
1916TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1917 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1918 sp<FakeWindowHandle> window =
1919 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1920
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001921 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001922 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001923 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1924 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1925 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001926 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001927 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1928 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1929 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1930 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001931 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001932 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1933 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1934 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1935 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001936 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1937 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1938 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1939
1940 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001941 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001942 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1943 window->consumeMotionEvent(
1944 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1945}
1946
1947/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001948 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1949 * with the following differences:
1950 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1951 * clean up the connection.
1952 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1953 * Ensure that there's no crash in the dispatcher.
1954 */
1955TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1956 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1957 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001958 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001959 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001960 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001961 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001962 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001963
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001964 mDispatcher->onWindowInfosChanged(
1965 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001966 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001967 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001968 {100, 200}))
1969 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1970
1971 // Both foreground window and its wallpaper should receive the touch down
1972 foregroundWindow->consumeMotionDown();
1973 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1974
1975 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001976 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001977 ADISPLAY_ID_DEFAULT, {110, 200}))
1978 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1979
1980 foregroundWindow->consumeMotionMove();
1981 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1982
1983 // Wallpaper closes its channel, but the window remains.
1984 wallpaperWindow->destroyReceiver();
1985 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1986
1987 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1988 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001989 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001990 foregroundWindow->consumeMotionCancel();
1991}
1992
Arthur Hungc539dbb2022-12-08 07:45:36 +00001993class ShouldSplitTouchFixture : public InputDispatcherTest,
1994 public ::testing::WithParamInterface<bool> {};
1995INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1996 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001997/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001998 * A single window that receives touch (on top), and a wallpaper window underneath it.
1999 * The top window gets a multitouch gesture.
2000 * Ensure that wallpaper gets the same gesture.
2001 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00002002TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002003 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002004 sp<FakeWindowHandle> foregroundWindow =
2005 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
2006 foregroundWindow->setDupTouchToWallpaper(true);
2007 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002008
2009 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002010 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002011 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002012
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002013 mDispatcher->onWindowInfosChanged(
2014 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002015
2016 // Touch down on top window
2017 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002018 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002019 {100, 100}))
2020 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2021
2022 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00002023 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002024 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2025
2026 // Second finger down on the top window
2027 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002028 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002029 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002030 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2031 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002032 .build();
2033 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002034 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002035 InputEventInjectionSync::WAIT_FOR_RESULT))
2036 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2037
Harry Cutts33476232023-01-30 19:57:29 +00002038 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
2039 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002040 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00002041
2042 const MotionEvent secondFingerUpEvent =
2043 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2044 .displayId(ADISPLAY_ID_DEFAULT)
2045 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002046 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2047 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002048 .build();
2049 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002050 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002051 InputEventInjectionSync::WAIT_FOR_RESULT))
2052 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2053 foregroundWindow->consumeMotionPointerUp(0);
2054 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2055
2056 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002057 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002058 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2059 AINPUT_SOURCE_TOUCHSCREEN)
2060 .displayId(ADISPLAY_ID_DEFAULT)
2061 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00002062 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002063 .x(100)
2064 .y(100))
2065 .build(),
2066 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002067 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2068 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2069 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002070}
2071
2072/**
2073 * Two windows: a window on the left and window on the right.
2074 * A third window, wallpaper, is behind both windows, and spans both top windows.
2075 * The first touch down goes to the left window. A second pointer touches down on the right window.
2076 * The touch is split, so both left and right windows should receive ACTION_DOWN.
2077 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
2078 * ACTION_POINTER_DOWN(1).
2079 */
2080TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
2081 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2082 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002083 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002084 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002085 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002086
2087 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002088 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002089 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002090 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002091
2092 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002093 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002094 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002095 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002096
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002097 mDispatcher->onWindowInfosChanged(
2098 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2099 {},
2100 0,
2101 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002102
2103 // Touch down on left window
2104 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002105 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002106 {100, 100}))
2107 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2108
2109 // Both foreground window and its wallpaper should receive the touch down
2110 leftWindow->consumeMotionDown();
2111 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2112
2113 // Second finger down on the right window
2114 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002115 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002116 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002117 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2118 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002119 .build();
2120 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002121 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002122 InputEventInjectionSync::WAIT_FOR_RESULT))
2123 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2124
2125 leftWindow->consumeMotionMove();
2126 // Since the touch is split, right window gets ACTION_DOWN
2127 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002128 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002129 expectedWallpaperFlags);
2130
2131 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002132 mDispatcher->onWindowInfosChanged(
2133 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002134 leftWindow->consumeMotionCancel();
2135 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2136 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2137
2138 // The pointer that's still down on the right window moves, and goes to the right window only.
2139 // As far as the dispatcher's concerned though, both pointers are still present.
2140 const MotionEvent secondFingerMoveEvent =
2141 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2142 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002143 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2144 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002145 .build();
2146 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002147 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002148 InputEventInjectionSync::WAIT_FOR_RESULT));
2149 rightWindow->consumeMotionMove();
2150
2151 leftWindow->assertNoEvents();
2152 rightWindow->assertNoEvents();
2153 wallpaperWindow->assertNoEvents();
2154}
2155
Arthur Hungc539dbb2022-12-08 07:45:36 +00002156/**
2157 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2158 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2159 * The right window should receive ACTION_DOWN.
2160 */
2161TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002162 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002163 sp<FakeWindowHandle> leftWindow =
2164 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2165 leftWindow->setFrame(Rect(0, 0, 200, 200));
2166 leftWindow->setDupTouchToWallpaper(true);
2167 leftWindow->setSlippery(true);
2168
2169 sp<FakeWindowHandle> rightWindow =
2170 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2171 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002172
2173 sp<FakeWindowHandle> wallpaperWindow =
2174 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2175 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002176
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002177 mDispatcher->onWindowInfosChanged(
2178 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2179 {},
2180 0,
2181 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002182
Arthur Hungc539dbb2022-12-08 07:45:36 +00002183 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002184 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002185 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002186 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002187 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002188
2189 // Both foreground window and its wallpaper should receive the touch down
2190 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002191 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2192
Arthur Hungc539dbb2022-12-08 07:45:36 +00002193 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002194 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002195 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002196 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002197 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2198
Arthur Hungc539dbb2022-12-08 07:45:36 +00002199 leftWindow->consumeMotionCancel();
2200 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2201 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002202}
2203
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002204/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002205 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2206 * interactive, it might stop sending this flag.
2207 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2208 * to have a consistent input stream.
2209 *
2210 * Test procedure:
2211 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2212 * DOWN (new gesture).
2213 *
2214 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2215 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2216 *
2217 * We technically just need a single window here, but we are using two windows (spy on top and a
2218 * regular window below) to emulate the actual situation where it happens on the device.
2219 */
2220TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2221 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2222 sp<FakeWindowHandle> spyWindow =
2223 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2224 spyWindow->setFrame(Rect(0, 0, 200, 200));
2225 spyWindow->setTrustedOverlay(true);
2226 spyWindow->setSpy(true);
2227
2228 sp<FakeWindowHandle> window =
2229 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2230 window->setFrame(Rect(0, 0, 200, 200));
2231
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002232 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002233 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002234
2235 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002236 mDispatcher->notifyMotion(
2237 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2238 .deviceId(touchDeviceId)
2239 .policyFlags(DEFAULT_POLICY_FLAGS)
2240 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2241 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002242
Prabir Pradhan678438e2023-04-13 19:32:51 +00002243 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2244 .deviceId(touchDeviceId)
2245 .policyFlags(DEFAULT_POLICY_FLAGS)
2246 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2247 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2248 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002249 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2250 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2251 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2252 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2253
2254 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002255 mDispatcher->notifyMotion(
2256 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2257 .deviceId(touchDeviceId)
2258 .policyFlags(0)
2259 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2260 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2261 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002262 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2263 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2264
2265 // We don't need to reset the device to reproduce the issue, but the reset event typically
2266 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002267 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002268
2269 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002270 mDispatcher->notifyMotion(
2271 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2272 .deviceId(touchDeviceId)
2273 .policyFlags(DEFAULT_POLICY_FLAGS)
2274 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2275 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002276 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2277 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2278
2279 // No more events
2280 spyWindow->assertNoEvents();
2281 window->assertNoEvents();
2282}
2283
2284/**
Linnan Li907ae732023-09-05 17:14:21 +08002285 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
2286 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2287 * interactive, it might stop sending this flag.
2288 * We've already ensured the consistency of the touch event in this case, and we should also ensure
2289 * the consistency of the hover event in this case.
2290 *
2291 * Test procedure:
2292 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
2293 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
2294 *
2295 * We expect to receive two full streams of hover events.
2296 */
2297TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
2298 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2299
2300 sp<FakeWindowHandle> window =
2301 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2302 window->setFrame(Rect(0, 0, 300, 300));
2303
2304 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2305
2306 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2307 .policyFlags(DEFAULT_POLICY_FLAGS)
2308 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2309 .build());
2310 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2311
2312 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2313 .policyFlags(DEFAULT_POLICY_FLAGS)
2314 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2315 .build());
2316 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2317
2318 // Send hover exit without the default policy flags.
2319 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2320 .policyFlags(0)
2321 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2322 .build());
2323
2324 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2325
2326 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
2327 // right event.
2328 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2329 .policyFlags(DEFAULT_POLICY_FLAGS)
2330 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
2331 .build());
2332 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2333
2334 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2335 .policyFlags(DEFAULT_POLICY_FLAGS)
2336 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2337 .build());
2338 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2339
2340 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2341 .policyFlags(DEFAULT_POLICY_FLAGS)
2342 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2343 .build());
2344 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2345}
2346
2347/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002348 * Two windows: a window on the left and a window on the right.
2349 * Mouse is hovered from the right window into the left window.
2350 * Next, we tap on the left window, where the cursor was last seen.
2351 * The second tap is done onto the right window.
2352 * The mouse and tap are from two different devices.
2353 * We technically don't need to set the downtime / eventtime for these events, but setting these
2354 * explicitly helps during debugging.
2355 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2356 * In the buggy implementation, a tap on the right window would cause a crash.
2357 */
2358TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2359 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2360 sp<FakeWindowHandle> leftWindow =
2361 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2362 leftWindow->setFrame(Rect(0, 0, 200, 200));
2363
2364 sp<FakeWindowHandle> rightWindow =
2365 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2366 rightWindow->setFrame(Rect(200, 0, 400, 200));
2367
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002368 mDispatcher->onWindowInfosChanged(
2369 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002370 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2371 // stale.
2372 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2373 const int32_t mouseDeviceId = 6;
2374 const int32_t touchDeviceId = 4;
2375 // Move the cursor from right
2376 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002377 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002378 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2379 AINPUT_SOURCE_MOUSE)
2380 .deviceId(mouseDeviceId)
2381 .downTime(baseTime + 10)
2382 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002383 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002384 .build()));
2385 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2386
2387 // .. to the left window
2388 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002389 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002390 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2391 AINPUT_SOURCE_MOUSE)
2392 .deviceId(mouseDeviceId)
2393 .downTime(baseTime + 10)
2394 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002395 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002396 .build()));
2397 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2398 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2399 // Now tap the left window
2400 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002401 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002402 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2403 AINPUT_SOURCE_TOUCHSCREEN)
2404 .deviceId(touchDeviceId)
2405 .downTime(baseTime + 40)
2406 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002407 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002408 .build()));
2409 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2410 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2411
2412 // release tap
2413 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002414 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002415 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2416 AINPUT_SOURCE_TOUCHSCREEN)
2417 .deviceId(touchDeviceId)
2418 .downTime(baseTime + 40)
2419 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002420 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002421 .build()));
2422 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2423
2424 // Tap the window on the right
2425 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002426 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002427 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2428 AINPUT_SOURCE_TOUCHSCREEN)
2429 .deviceId(touchDeviceId)
2430 .downTime(baseTime + 60)
2431 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002432 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002433 .build()));
2434 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2435
2436 // release tap
2437 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002438 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002439 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2440 AINPUT_SOURCE_TOUCHSCREEN)
2441 .deviceId(touchDeviceId)
2442 .downTime(baseTime + 60)
2443 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002444 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002445 .build()));
2446 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2447
2448 // No more events
2449 leftWindow->assertNoEvents();
2450 rightWindow->assertNoEvents();
2451}
2452
2453/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002454 * Start hovering in a window. While this hover is still active, make another window appear on top.
2455 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2456 * While the top window is present, the hovering is stopped.
2457 * Later, hovering gets resumed again.
2458 * Ensure that new hover gesture is handled correctly.
2459 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2460 * to the window that's currently being hovered over.
2461 */
2462TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2463 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2464 sp<FakeWindowHandle> window =
2465 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2466 window->setFrame(Rect(0, 0, 200, 200));
2467
2468 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002469 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002470
2471 // Start hovering in the window
2472 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2473 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2474 .build());
2475 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2476
2477 // Now, an obscuring window appears!
2478 sp<FakeWindowHandle> obscuringWindow =
2479 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2480 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002481 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002482 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2483 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2484 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2485 obscuringWindow->setNoInputChannel(true);
2486 obscuringWindow->setFocusable(false);
2487 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002488 mDispatcher->onWindowInfosChanged(
2489 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002490
2491 // While this new obscuring window is present, the hovering is stopped
2492 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2493 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2494 .build());
2495 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2496
2497 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002498 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002499
2500 // And a new hover gesture starts.
2501 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2502 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2503 .build());
2504 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2505}
2506
2507/**
2508 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2509 * the obscuring window.
2510 */
2511TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2512 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2513 sp<FakeWindowHandle> window =
2514 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2515 window->setFrame(Rect(0, 0, 200, 200));
2516
2517 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002518 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002519
2520 // Start hovering in the window
2521 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2522 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2523 .build());
2524 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2525
2526 // Now, an obscuring window appears!
2527 sp<FakeWindowHandle> obscuringWindow =
2528 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2529 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002530 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002531 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2532 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2533 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2534 obscuringWindow->setNoInputChannel(true);
2535 obscuringWindow->setFocusable(false);
2536 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002537 mDispatcher->onWindowInfosChanged(
2538 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002539
2540 // While this new obscuring window is present, the hovering continues. The event can't go to the
2541 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2542 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2543 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2544 .build());
2545 obscuringWindow->assertNoEvents();
2546 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2547
2548 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002549 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002550
2551 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2552 // so it should generate a HOVER_ENTER
2553 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2554 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2555 .build());
2556 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2557
2558 // Now the MOVE should be getting dispatched normally
2559 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2560 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2561 .build());
2562 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2563}
2564
2565/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002566 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2567 * events are delivered to the window.
2568 */
2569TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2570 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2571 sp<FakeWindowHandle> window =
2572 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2573 window->setFrame(Rect(0, 0, 200, 200));
2574 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2575
2576 // Start hovering in the window
2577 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2578 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2579 .build());
2580 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2581
2582 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2583 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2584 .build());
2585 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2586
2587 // Scroll with the mouse
2588 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2589 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2590 .build());
2591 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2592}
2593
2594using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2595
2596/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002597 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2598 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002599 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002600TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002601 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2602 sp<FakeWindowHandle> window =
2603 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2604 window->setFrame(Rect(0, 0, 200, 200));
2605
2606 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2607
2608 constexpr int32_t touchDeviceId = 4;
2609 constexpr int32_t stylusDeviceId = 2;
2610
2611 // Stylus down
2612 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2613 .deviceId(stylusDeviceId)
2614 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2615 .build());
2616 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2617
2618 // Touch down
2619 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2620 .deviceId(touchDeviceId)
2621 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2622 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002623
2624 // Touch move
2625 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2626 .deviceId(touchDeviceId)
2627 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2628 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002629 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002630
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002631 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002632 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2633 .deviceId(stylusDeviceId)
2634 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2635 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002636 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2637 WithCoords(101, 111)));
2638
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002639 window->assertNoEvents();
2640}
2641
2642/**
2643 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002644 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002645 * Similar test as above, but with added SPY window.
2646 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002647TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002648 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2649 sp<FakeWindowHandle> window =
2650 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2651 sp<FakeWindowHandle> spyWindow =
2652 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2653 spyWindow->setFrame(Rect(0, 0, 200, 200));
2654 spyWindow->setTrustedOverlay(true);
2655 spyWindow->setSpy(true);
2656 window->setFrame(Rect(0, 0, 200, 200));
2657
2658 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2659
2660 constexpr int32_t touchDeviceId = 4;
2661 constexpr int32_t stylusDeviceId = 2;
2662
2663 // Stylus down
2664 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2665 .deviceId(stylusDeviceId)
2666 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2667 .build());
2668 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2669 spyWindow->consumeMotionEvent(
2670 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2671
2672 // Touch down
2673 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2674 .deviceId(touchDeviceId)
2675 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2676 .build());
2677
2678 // Touch move
2679 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2680 .deviceId(touchDeviceId)
2681 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2682 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002683
2684 // Touch is ignored because stylus is already down
2685
2686 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002687 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2688 .deviceId(stylusDeviceId)
2689 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2690 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002691 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2692 WithCoords(101, 111)));
2693 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2694 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002695
2696 window->assertNoEvents();
2697 spyWindow->assertNoEvents();
2698}
2699
2700/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002701 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002702 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002703 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002704TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002705 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2706 sp<FakeWindowHandle> window =
2707 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2708 window->setFrame(Rect(0, 0, 200, 200));
2709
2710 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2711
2712 constexpr int32_t touchDeviceId = 4;
2713 constexpr int32_t stylusDeviceId = 2;
2714
2715 // Stylus down on the window
2716 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2717 .deviceId(stylusDeviceId)
2718 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2719 .build());
2720 window->consumeMotionEvent(
2721 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2722
2723 // Touch down on window
2724 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2725 .deviceId(touchDeviceId)
2726 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2727 .build());
2728 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2729 .deviceId(touchDeviceId)
2730 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2731 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002732
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002733 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002734
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002735 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002736 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2737 .deviceId(stylusDeviceId)
2738 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2739 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002740 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2741 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002742
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002743 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002744 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2745 .deviceId(touchDeviceId)
2746 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2747 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002748 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002749}
2750
2751/**
2752 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002753 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002754 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002755TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002756 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2757 sp<FakeWindowHandle> window =
2758 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2759 window->setFrame(Rect(0, 0, 200, 200));
2760
2761 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2762
2763 constexpr int32_t touchDeviceId = 4;
2764 constexpr int32_t stylusDeviceId = 2;
2765
2766 // Touch down on window
2767 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2768 .deviceId(touchDeviceId)
2769 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2770 .build());
2771 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2772 .deviceId(touchDeviceId)
2773 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2774 .build());
2775 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2776 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2777
2778 // Stylus hover on the window
2779 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2780 .deviceId(stylusDeviceId)
2781 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2782 .build());
2783 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2784 .deviceId(stylusDeviceId)
2785 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2786 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002787 // Stylus hover movement causes touch to be canceled
2788 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2789 WithCoords(141, 146)));
2790 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2791 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2792 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2793 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002794
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002795 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002796 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2797 .deviceId(touchDeviceId)
2798 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2799 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002800
2801 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002802}
2803
2804/**
2805 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2806 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2807 * become active.
2808 */
2809TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
2810 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2811 sp<FakeWindowHandle> window =
2812 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2813 window->setFrame(Rect(0, 0, 200, 200));
2814
2815 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2816
2817 constexpr int32_t stylusDeviceId1 = 3;
2818 constexpr int32_t stylusDeviceId2 = 5;
2819
2820 // Touch down on window
2821 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2822 .deviceId(stylusDeviceId1)
2823 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2824 .build());
2825 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2826 .deviceId(stylusDeviceId1)
2827 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2828 .build());
2829 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2830 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2831
2832 // Second stylus down
2833 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2834 .deviceId(stylusDeviceId2)
2835 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2836 .build());
2837 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2838 .deviceId(stylusDeviceId2)
2839 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2840 .build());
2841
2842 // First stylus is canceled, second one takes over.
2843 window->consumeMotionEvent(
2844 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2845 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2846 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2847
2848 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2849 .deviceId(stylusDeviceId1)
2850 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2851 .build());
2852 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002853 window->assertNoEvents();
2854}
2855
2856/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002857 * One window. Touch down on the window. Then, stylus down on the window from another device.
2858 * Ensure that is canceled, because stylus down should be preferred over touch.
2859 */
2860TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
2861 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2862 sp<FakeWindowHandle> window =
2863 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2864 window->setFrame(Rect(0, 0, 200, 200));
2865
2866 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2867
2868 constexpr int32_t touchDeviceId = 4;
2869 constexpr int32_t stylusDeviceId = 2;
2870
2871 // Touch down on window
2872 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2873 .deviceId(touchDeviceId)
2874 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2875 .build());
2876 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2877 .deviceId(touchDeviceId)
2878 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2879 .build());
2880 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2881 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2882
2883 // Stylus down on the window
2884 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2885 .deviceId(stylusDeviceId)
2886 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2887 .build());
2888 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2889 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2890
2891 // Subsequent stylus movements are delivered correctly
2892 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2893 .deviceId(stylusDeviceId)
2894 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2895 .build());
2896 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2897 WithCoords(101, 111)));
2898}
2899
2900/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002901 * Two windows: a window on the left and a window on the right.
2902 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2903 * down. Then, on the left window, also place second touch pointer down.
2904 * This test tries to reproduce a crash.
2905 * In the buggy implementation, second pointer down on the left window would cause a crash.
2906 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002907TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002908 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2909 sp<FakeWindowHandle> leftWindow =
2910 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2911 leftWindow->setFrame(Rect(0, 0, 200, 200));
2912
2913 sp<FakeWindowHandle> rightWindow =
2914 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2915 rightWindow->setFrame(Rect(200, 0, 400, 200));
2916
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002917 mDispatcher->onWindowInfosChanged(
2918 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002919
2920 const int32_t touchDeviceId = 4;
2921 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002922
2923 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002924 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2925 .deviceId(mouseDeviceId)
2926 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2927 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002928 leftWindow->consumeMotionEvent(
2929 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2930
2931 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002932 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2933 .deviceId(mouseDeviceId)
2934 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2935 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2936 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002937
2938 leftWindow->consumeMotionEvent(
2939 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2940 leftWindow->consumeMotionEvent(
2941 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2942
Prabir Pradhan678438e2023-04-13 19:32:51 +00002943 mDispatcher->notifyMotion(
2944 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2945 .deviceId(mouseDeviceId)
2946 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2947 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2948 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2949 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002950 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2951
2952 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002953 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2954 .deviceId(touchDeviceId)
2955 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2956 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002957 leftWindow->assertNoEvents();
2958
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002959 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2960
2961 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002962 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2963 .deviceId(touchDeviceId)
2964 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2965 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2966 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002967 // Since this is now a new splittable pointer going down on the left window, and it's coming
2968 // from a different device, the current gesture in the left window (pointer down) should first
2969 // be canceled.
2970 leftWindow->consumeMotionEvent(
2971 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002972 leftWindow->consumeMotionEvent(
2973 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2974 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2975 // current implementation.
2976 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2977 rightWindow->consumeMotionEvent(
2978 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2979
2980 leftWindow->assertNoEvents();
2981 rightWindow->assertNoEvents();
2982}
2983
2984/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002985 * Two windows: a window on the left and a window on the right.
2986 * Mouse is hovered on the left window and stylus is hovered on the right window.
2987 */
2988TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2989 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2990 sp<FakeWindowHandle> leftWindow =
2991 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2992 leftWindow->setFrame(Rect(0, 0, 200, 200));
2993
2994 sp<FakeWindowHandle> rightWindow =
2995 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2996 rightWindow->setFrame(Rect(200, 0, 400, 200));
2997
2998 mDispatcher->onWindowInfosChanged(
2999 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3000
3001 const int32_t stylusDeviceId = 3;
3002 const int32_t mouseDeviceId = 6;
3003
3004 // Start hovering over the left window
3005 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3006 .deviceId(mouseDeviceId)
3007 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
3008 .build());
3009 leftWindow->consumeMotionEvent(
3010 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3011
3012 // Stylus hovered on right window
3013 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3014 .deviceId(stylusDeviceId)
3015 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
3016 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003017 rightWindow->consumeMotionEvent(
3018 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3019
3020 // Subsequent HOVER_MOVE events are dispatched correctly.
3021 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
3022 .deviceId(mouseDeviceId)
3023 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
3024 .build());
3025 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003026 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003027
3028 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3029 .deviceId(stylusDeviceId)
3030 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
3031 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003032 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003033 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003034
3035 leftWindow->assertNoEvents();
3036 rightWindow->assertNoEvents();
3037}
3038
3039/**
3040 * Three windows: a window on the left and a window on the right.
3041 * And a spy window that's positioned above all of them.
3042 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
3043 * Check the stream that's received by the spy.
3044 */
3045TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
3046 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3047
3048 sp<FakeWindowHandle> spyWindow =
3049 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3050 spyWindow->setFrame(Rect(0, 0, 400, 400));
3051 spyWindow->setTrustedOverlay(true);
3052 spyWindow->setSpy(true);
3053
3054 sp<FakeWindowHandle> leftWindow =
3055 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3056 leftWindow->setFrame(Rect(0, 0, 200, 200));
3057
3058 sp<FakeWindowHandle> rightWindow =
3059 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3060
3061 rightWindow->setFrame(Rect(200, 0, 400, 200));
3062
3063 mDispatcher->onWindowInfosChanged(
3064 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3065
3066 const int32_t stylusDeviceId = 1;
3067 const int32_t touchDeviceId = 2;
3068
3069 // Stylus down on the left window
3070 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3071 .deviceId(stylusDeviceId)
3072 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3073 .build());
3074 leftWindow->consumeMotionEvent(
3075 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3076 spyWindow->consumeMotionEvent(
3077 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3078
3079 // Touch down on the right window
3080 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3081 .deviceId(touchDeviceId)
3082 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3083 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003084 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003085 rightWindow->consumeMotionEvent(
3086 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003087
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003088 // Spy window does not receive touch events, because stylus events take precedence, and it
3089 // already has an active stylus gesture.
3090
3091 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003092 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3093 .deviceId(stylusDeviceId)
3094 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3095 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003096 leftWindow->consumeMotionEvent(
3097 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3098 spyWindow->consumeMotionEvent(
3099 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003100
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003101 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003102 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3103 .deviceId(touchDeviceId)
3104 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
3105 .build());
3106 rightWindow->consumeMotionEvent(
3107 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003108
3109 spyWindow->assertNoEvents();
3110 leftWindow->assertNoEvents();
3111 rightWindow->assertNoEvents();
3112}
3113
3114/**
3115 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3116 * both.
3117 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003118 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003119 * At the same time, left and right should be getting independent streams of hovering and touch,
3120 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003121 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003122TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003123 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3124
3125 sp<FakeWindowHandle> spyWindow =
3126 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3127 spyWindow->setFrame(Rect(0, 0, 400, 400));
3128 spyWindow->setTrustedOverlay(true);
3129 spyWindow->setSpy(true);
3130
3131 sp<FakeWindowHandle> leftWindow =
3132 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3133 leftWindow->setFrame(Rect(0, 0, 200, 200));
3134
3135 sp<FakeWindowHandle> rightWindow =
3136 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3137 rightWindow->setFrame(Rect(200, 0, 400, 200));
3138
3139 mDispatcher->onWindowInfosChanged(
3140 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3141
3142 const int32_t stylusDeviceId = 1;
3143 const int32_t touchDeviceId = 2;
3144
3145 // Stylus hover on the left window
3146 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3147 .deviceId(stylusDeviceId)
3148 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3149 .build());
3150 leftWindow->consumeMotionEvent(
3151 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3152 spyWindow->consumeMotionEvent(
3153 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3154
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003155 // Touch down on the right window. Spy doesn't receive this touch because it already has
3156 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003157 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3158 .deviceId(touchDeviceId)
3159 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3160 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003161 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003162 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003163 rightWindow->consumeMotionEvent(
3164 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3165
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003166 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003167 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3168 .deviceId(stylusDeviceId)
3169 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3170 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003171 leftWindow->consumeMotionEvent(
3172 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003173 spyWindow->consumeMotionEvent(
3174 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003175
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003176 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003177 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3178 .deviceId(touchDeviceId)
3179 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3180 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003181 rightWindow->consumeMotionEvent(
3182 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3183
3184 spyWindow->assertNoEvents();
3185 leftWindow->assertNoEvents();
3186 rightWindow->assertNoEvents();
3187}
3188
3189/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003190 * On a single window, use two different devices: mouse and touch.
3191 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3192 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3193 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3194 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3195 * represent a new gesture.
3196 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003197TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003198 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3199 sp<FakeWindowHandle> window =
3200 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3201 window->setFrame(Rect(0, 0, 400, 400));
3202
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003203 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003204
3205 const int32_t touchDeviceId = 4;
3206 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003207
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003208 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003209 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3210 .deviceId(touchDeviceId)
3211 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3212 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003213 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003214 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3215 .deviceId(touchDeviceId)
3216 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3217 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3218 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003219 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003220 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3221 .deviceId(touchDeviceId)
3222 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3223 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3224 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003225 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3226 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3227 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3228
3229 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003230 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3231 .deviceId(mouseDeviceId)
3232 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3233 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3234 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003235
3236 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003237 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003238 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3239
Prabir Pradhan678438e2023-04-13 19:32:51 +00003240 mDispatcher->notifyMotion(
3241 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3242 .deviceId(mouseDeviceId)
3243 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3244 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3245 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3246 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003247 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3248
3249 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003250 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3251 .deviceId(touchDeviceId)
3252 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3253 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3254 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003255 // Since we already canceled this touch gesture, it will be ignored until a completely new
3256 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3257 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3258 // However, mouse movements should continue to work.
3259 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3260 .deviceId(mouseDeviceId)
3261 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3262 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3263 .build());
3264 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3265
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003266 window->assertNoEvents();
3267}
3268
3269/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003270 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3271 * the injected event.
3272 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003273TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003274 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3275 sp<FakeWindowHandle> window =
3276 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3277 window->setFrame(Rect(0, 0, 400, 400));
3278
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003279 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003280
3281 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003282 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3283 // completion.
3284 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003285 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003286 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3287 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003288 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003289 .build()));
3290 window->consumeMotionEvent(
3291 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3292
3293 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3294 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003295 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3296 .deviceId(touchDeviceId)
3297 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3298 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003299
3300 window->consumeMotionEvent(
3301 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3302 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3303}
3304
3305/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003306 * This test is similar to the test above, but the sequence of injected events is different.
3307 *
3308 * Two windows: a window on the left and a window on the right.
3309 * Mouse is hovered over the left window.
3310 * Next, we tap on the left window, where the cursor was last seen.
3311 *
3312 * After that, we inject one finger down onto the right window, and then a second finger down onto
3313 * the left window.
3314 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3315 * window (first), and then another on the left window (second).
3316 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3317 * In the buggy implementation, second finger down on the left window would cause a crash.
3318 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003319TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003320 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3321 sp<FakeWindowHandle> leftWindow =
3322 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3323 leftWindow->setFrame(Rect(0, 0, 200, 200));
3324
3325 sp<FakeWindowHandle> rightWindow =
3326 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3327 rightWindow->setFrame(Rect(200, 0, 400, 200));
3328
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003329 mDispatcher->onWindowInfosChanged(
3330 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003331
3332 const int32_t mouseDeviceId = 6;
3333 const int32_t touchDeviceId = 4;
3334 // Hover over the left window. Keep the cursor there.
3335 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003336 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003337 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3338 AINPUT_SOURCE_MOUSE)
3339 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003340 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003341 .build()));
3342 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3343
3344 // Tap on left window
3345 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003346 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003347 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3348 AINPUT_SOURCE_TOUCHSCREEN)
3349 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003350 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003351 .build()));
3352
3353 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003354 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003355 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3356 AINPUT_SOURCE_TOUCHSCREEN)
3357 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003358 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003359 .build()));
3360 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3361 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3362 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3363
3364 // First finger down on right window
3365 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003366 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003367 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3368 AINPUT_SOURCE_TOUCHSCREEN)
3369 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003370 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003371 .build()));
3372 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3373
3374 // Second finger down on the left window
3375 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003376 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003377 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3378 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003379 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3380 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003381 .build()));
3382 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3383 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3384
3385 // No more events
3386 leftWindow->assertNoEvents();
3387 rightWindow->assertNoEvents();
3388}
3389
3390/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003391 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3392 * While the touch is down, new hover events from the stylus device should be ignored. After the
3393 * touch is gone, stylus hovering should start working again.
3394 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003395TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003396 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3397 sp<FakeWindowHandle> window =
3398 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3399 window->setFrame(Rect(0, 0, 200, 200));
3400
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003401 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003402
3403 const int32_t stylusDeviceId = 5;
3404 const int32_t touchDeviceId = 4;
3405 // Start hovering with stylus
3406 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003407 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003408 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003409 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003410 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003411 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003412 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003413
3414 // Finger down on the window
3415 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003416 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003417 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003418 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003419 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003420 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003421 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003422
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003423 // Continue hovering with stylus.
3424 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003425 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003426 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3427 AINPUT_SOURCE_STYLUS)
3428 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003429 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003430 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003431 // Hovers continue to work
3432 window->consumeMotionEvent(
3433 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003434
3435 // Lift up the finger
3436 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003437 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003438 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3439 AINPUT_SOURCE_TOUCHSCREEN)
3440 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003441 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003442 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003443
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003444 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003445 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003446 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3447 AINPUT_SOURCE_STYLUS)
3448 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003449 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003450 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003451 window->consumeMotionEvent(
3452 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003453 window->assertNoEvents();
3454}
3455
3456/**
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003457 * If stylus is down anywhere on the screen, then touches should not be delivered to windows that
3458 * have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3459 *
3460 * Two windows: one on the left and one on the right.
3461 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3462 * Stylus down on the left window, and then touch down on the right window.
3463 * Check that the right window doesn't get touches while the stylus is down on the left window.
3464 */
3465TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusDownBlocksTouch) {
3466 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3467 sp<FakeWindowHandle> leftWindow =
3468 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3469 ADISPLAY_ID_DEFAULT);
3470 leftWindow->setFrame(Rect(0, 0, 100, 100));
3471
3472 sp<FakeWindowHandle> sbtRightWindow =
3473 sp<FakeWindowHandle>::make(application, mDispatcher,
3474 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3475 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3476 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3477
3478 mDispatcher->onWindowInfosChanged(
3479 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3480
3481 const int32_t stylusDeviceId = 5;
3482 const int32_t touchDeviceId = 4;
3483
3484 // Stylus down in the left window
3485 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3486 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3487 .deviceId(stylusDeviceId)
3488 .build());
3489 leftWindow->consumeMotionEvent(
3490 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3491
3492 // Finger tap on the right window
3493 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3494 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3495 .deviceId(touchDeviceId)
3496 .build());
3497 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3498 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3499 .deviceId(touchDeviceId)
3500 .build());
3501
3502 // The touch should be blocked, because stylus is down somewhere else on screen!
3503 sbtRightWindow->assertNoEvents();
3504
3505 // Continue stylus motion, and ensure it's not impacted.
3506 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3507 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3508 .deviceId(stylusDeviceId)
3509 .build());
3510 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3511 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3512 .deviceId(stylusDeviceId)
3513 .build());
3514 leftWindow->consumeMotionEvent(
3515 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3516 leftWindow->consumeMotionEvent(
3517 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(stylusDeviceId)));
3518
3519 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3520 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3521 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3522 .deviceId(touchDeviceId)
3523 .build());
3524 sbtRightWindow->consumeMotionEvent(
3525 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3526}
3527
3528/**
3529 * If stylus is hovering anywhere on the screen, then touches should not be delivered to windows
3530 * that have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3531 *
3532 * Two windows: one on the left and one on the right.
3533 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3534 * Stylus hover on the left window, and then touch down on the right window.
3535 * Check that the right window doesn't get touches while the stylus is hovering on the left window.
3536 */
3537TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusHoverBlocksTouch) {
3538 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3539 sp<FakeWindowHandle> leftWindow =
3540 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3541 ADISPLAY_ID_DEFAULT);
3542 leftWindow->setFrame(Rect(0, 0, 100, 100));
3543
3544 sp<FakeWindowHandle> sbtRightWindow =
3545 sp<FakeWindowHandle>::make(application, mDispatcher,
3546 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3547 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3548 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3549
3550 mDispatcher->onWindowInfosChanged(
3551 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3552
3553 const int32_t stylusDeviceId = 5;
3554 const int32_t touchDeviceId = 4;
3555
3556 // Stylus hover in the left window
3557 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3558 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3559 .deviceId(stylusDeviceId)
3560 .build());
3561 leftWindow->consumeMotionEvent(
3562 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3563
3564 // Finger tap on the right window
3565 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3566 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3567 .deviceId(touchDeviceId)
3568 .build());
3569 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3570 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3571 .deviceId(touchDeviceId)
3572 .build());
3573
3574 // The touch should be blocked, because stylus is hovering somewhere else on screen!
3575 sbtRightWindow->assertNoEvents();
3576
3577 // Continue stylus motion, and ensure it's not impacted.
3578 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3579 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3580 .deviceId(stylusDeviceId)
3581 .build());
3582 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3583 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3584 .deviceId(stylusDeviceId)
3585 .build());
3586 leftWindow->consumeMotionEvent(
3587 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3588 leftWindow->consumeMotionEvent(
3589 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3590
3591 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3592 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3593 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3594 .deviceId(touchDeviceId)
3595 .build());
3596 sbtRightWindow->consumeMotionEvent(
3597 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3598}
3599
3600/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003601 * A spy window above a window with no input channel.
3602 * Start hovering with a stylus device, and then tap with it.
3603 * Ensure spy window receives the entire sequence.
3604 */
3605TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3606 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3607 sp<FakeWindowHandle> spyWindow =
3608 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3609 spyWindow->setFrame(Rect(0, 0, 200, 200));
3610 spyWindow->setTrustedOverlay(true);
3611 spyWindow->setSpy(true);
3612 sp<FakeWindowHandle> window =
3613 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3614 window->setNoInputChannel(true);
3615 window->setFrame(Rect(0, 0, 200, 200));
3616
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003617 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003618
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003619 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003620 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3621 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3622 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003623 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3624 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003625 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3626 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3627 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003628 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3629
3630 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003631 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3632 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3633 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003634 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3635
3636 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003637 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3638 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3639 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003640 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3641
3642 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003643 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3644 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3645 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003646 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3647 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003648 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3649 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3650 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003651 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3652
3653 // No more events
3654 spyWindow->assertNoEvents();
3655 window->assertNoEvents();
3656}
3657
3658/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003659 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3660 * rejected. But since we already have an ongoing gesture, this event should be processed.
3661 * This prevents inconsistent events being handled inside the dispatcher.
3662 */
3663TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3664 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3665
3666 sp<FakeWindowHandle> window =
3667 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3668 window->setFrame(Rect(0, 0, 200, 200));
3669
3670 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3671
3672 // Start hovering with stylus
3673 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3674 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3675 .build());
3676 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3677
3678 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3679 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3680 .build();
3681 // Make this 'hoverExit' event stale
3682 mFakePolicy->setStaleEventTimeout(100ms);
3683 std::this_thread::sleep_for(100ms);
3684
3685 // It shouldn't be dropped by the dispatcher, even though it's stale.
3686 mDispatcher->notifyMotion(hoverExit);
3687 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3688
3689 // Stylus starts hovering again! There should be no crash.
3690 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3691 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3692 .build());
3693 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3694}
3695
3696/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003697 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3698 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3699 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3700 * While the mouse is down, new move events from the touch device should be ignored.
3701 */
3702TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3703 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3704 sp<FakeWindowHandle> spyWindow =
3705 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3706 spyWindow->setFrame(Rect(0, 0, 200, 200));
3707 spyWindow->setTrustedOverlay(true);
3708 spyWindow->setSpy(true);
3709 sp<FakeWindowHandle> window =
3710 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3711 window->setFrame(Rect(0, 0, 200, 200));
3712
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003713 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003714
3715 const int32_t mouseDeviceId = 7;
3716 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003717
3718 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003719 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3720 .deviceId(mouseDeviceId)
3721 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3722 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003723 spyWindow->consumeMotionEvent(
3724 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3725 window->consumeMotionEvent(
3726 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3727
3728 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003729 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3730 .deviceId(touchDeviceId)
3731 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3732 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003733 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3734 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3735 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3736 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3737
Prabir Pradhan678438e2023-04-13 19:32:51 +00003738 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3739 .deviceId(touchDeviceId)
3740 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3741 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003742 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3743 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3744
3745 // Pilfer the stream
3746 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3747 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3748
Prabir Pradhan678438e2023-04-13 19:32:51 +00003749 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3750 .deviceId(touchDeviceId)
3751 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3752 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003753 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3754
3755 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003756 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3757 .deviceId(mouseDeviceId)
3758 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3759 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3760 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003761
3762 spyWindow->consumeMotionEvent(
3763 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3764 spyWindow->consumeMotionEvent(
3765 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3766 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3767
Prabir Pradhan678438e2023-04-13 19:32:51 +00003768 mDispatcher->notifyMotion(
3769 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3770 .deviceId(mouseDeviceId)
3771 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3772 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3773 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3774 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003775 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3776 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3777
3778 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003779 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3780 .deviceId(mouseDeviceId)
3781 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3782 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3783 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003784 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3785 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3786
3787 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003788 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3789 .deviceId(touchDeviceId)
3790 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3791 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003792
3793 // No more events
3794 spyWindow->assertNoEvents();
3795 window->assertNoEvents();
3796}
3797
3798/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003799 * On the display, have a single window, and also an area where there's no window.
3800 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3801 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3802 */
3803TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3804 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3805 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003806 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003807
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003808 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003809
3810 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003811 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003812
3813 mDispatcher->waitForIdle();
3814 window->assertNoEvents();
3815
3816 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003817 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003818 mDispatcher->waitForIdle();
3819 window->consumeMotionDown();
3820}
3821
3822/**
3823 * Same test as above, but instead of touching the empty space, the first touch goes to
3824 * non-touchable window.
3825 */
3826TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3827 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3828 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003829 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003830 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3831 window1->setTouchable(false);
3832 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003833 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003834 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3835
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003836 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003837
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003838 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003839 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003840
3841 mDispatcher->waitForIdle();
3842 window1->assertNoEvents();
3843 window2->assertNoEvents();
3844
3845 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003846 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003847 mDispatcher->waitForIdle();
3848 window2->consumeMotionDown();
3849}
3850
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003851/**
3852 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3853 * to the event time of the first ACTION_DOWN sent to the particular window.
3854 */
3855TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3856 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3857 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003858 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003859 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3860 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003861 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003862 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3863
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003864 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003865
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003866 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003867 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003868 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003869
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003870 const std::unique_ptr<MotionEvent> firstDown =
3871 window1->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
3872 ASSERT_EQ(firstDown->getDownTime(), firstDown->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003873 window2->assertNoEvents();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003874
3875 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003876 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003877 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003878
3879 const std::unique_ptr<MotionEvent> secondDown =
3880 window2->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
3881 ASSERT_EQ(secondDown->getDownTime(), secondDown->getEventTime());
3882 ASSERT_NE(firstDown->getDownTime(), secondDown->getDownTime());
3883 // We currently send MOVE events to all windows receiving a split touch when there is any change
3884 // in the touch state, even when none of the pointers in the split window actually moved.
3885 // Document this behavior in the test.
3886 window1->consumeMotionMove();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003887
3888 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003889 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003890 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003891
3892 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
3893 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003894
3895 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003896 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003897 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003898
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003899 window2->consumeMotionEvent(
3900 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(secondDown->getDownTime())));
3901 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003902
3903 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003904 mDispatcher->notifyMotion(
3905 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003906 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003907
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003908 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
3909 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
3910
3911 // Now add new touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003912 mDispatcher->notifyMotion(
3913 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003914 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003915
3916 window1->consumeMotionEvent(
3917 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(firstDown->getDownTime())));
3918 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003919}
3920
Garfield Tandf26e862020-07-01 20:18:19 -07003921TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003922 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003923 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003924 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003925 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003926 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003927 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003928 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003929
3930 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3931
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003932 mDispatcher->onWindowInfosChanged(
3933 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003934
3935 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003936 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003937 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003938 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3939 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003940 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003941 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003942 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003943
3944 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003945 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003946 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003947 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3948 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003949 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003950 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003951 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3952 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003953
3954 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003955 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003956 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003957 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3958 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003959 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003960 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003961 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3962 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003963
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003964 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003965 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003966 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3967 AINPUT_SOURCE_MOUSE)
3968 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3969 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003970 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003971 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003972 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003973
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003974 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003975 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003976 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3977 AINPUT_SOURCE_MOUSE)
3978 .buttonState(0)
3979 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003980 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003981 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003982 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003983
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003984 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003985 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003986 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3987 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003988 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003989 .build()));
3990 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3991
3992 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003993 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003994 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003995 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3996 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003997 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003998 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003999 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004000
4001 // No more events
4002 windowLeft->assertNoEvents();
4003 windowRight->assertNoEvents();
4004}
4005
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004006/**
4007 * Put two fingers down (and don't release them) and click the mouse button.
4008 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
4009 * currently active gesture should be canceled, and the new one should proceed.
4010 */
4011TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
4012 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4013 sp<FakeWindowHandle> window =
4014 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4015 window->setFrame(Rect(0, 0, 600, 800));
4016
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004017 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004018
4019 const int32_t touchDeviceId = 4;
4020 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004021
4022 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004023 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4024 .deviceId(touchDeviceId)
4025 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4026 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004027
Prabir Pradhan678438e2023-04-13 19:32:51 +00004028 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4029 .deviceId(touchDeviceId)
4030 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4031 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4032 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004033 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4034 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4035
4036 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00004037 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4038 .deviceId(mouseDeviceId)
4039 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4040 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4041 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004042 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
4043 WithPointerCount(2u)));
4044 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4045
Prabir Pradhan678438e2023-04-13 19:32:51 +00004046 mDispatcher->notifyMotion(
4047 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4048 .deviceId(mouseDeviceId)
4049 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4050 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4051 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4052 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004053 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4054
4055 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4056 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004057 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4058 .deviceId(touchDeviceId)
4059 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4060 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4061 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004062 window->assertNoEvents();
4063}
4064
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004065TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
4066 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4067
4068 sp<FakeWindowHandle> spyWindow =
4069 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4070 spyWindow->setFrame(Rect(0, 0, 600, 800));
4071 spyWindow->setTrustedOverlay(true);
4072 spyWindow->setSpy(true);
4073 sp<FakeWindowHandle> window =
4074 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4075 window->setFrame(Rect(0, 0, 600, 800));
4076
4077 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004078 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004079
4080 // Send mouse cursor to the window
4081 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004082 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004083 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4084 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004085 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004086 .build()));
4087
4088 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4089 WithSource(AINPUT_SOURCE_MOUSE)));
4090 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4091 WithSource(AINPUT_SOURCE_MOUSE)));
4092
4093 window->assertNoEvents();
4094 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004095}
4096
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004097TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
4098 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4099
4100 sp<FakeWindowHandle> spyWindow =
4101 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4102 spyWindow->setFrame(Rect(0, 0, 600, 800));
4103 spyWindow->setTrustedOverlay(true);
4104 spyWindow->setSpy(true);
4105 sp<FakeWindowHandle> window =
4106 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4107 window->setFrame(Rect(0, 0, 600, 800));
4108
4109 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004110 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004111
4112 // Send mouse cursor to the window
4113 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004114 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004115 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4116 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004117 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004118 .build()));
4119
4120 // Move mouse cursor
4121 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004122 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004123 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4124 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004125 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004126 .build()));
4127
4128 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4129 WithSource(AINPUT_SOURCE_MOUSE)));
4130 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4131 WithSource(AINPUT_SOURCE_MOUSE)));
4132 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4133 WithSource(AINPUT_SOURCE_MOUSE)));
4134 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4135 WithSource(AINPUT_SOURCE_MOUSE)));
4136 // Touch down on the window
4137 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004138 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004139 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4140 AINPUT_SOURCE_TOUCHSCREEN)
4141 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004142 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004143 .build()));
4144 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4145 WithSource(AINPUT_SOURCE_MOUSE)));
4146 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4147 WithSource(AINPUT_SOURCE_MOUSE)));
4148 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4149 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4150 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4151 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4152
4153 // pilfer the motion, retaining the gesture on the spy window.
4154 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4155 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4156 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4157
4158 // Touch UP on the window
4159 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004160 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004161 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4162 AINPUT_SOURCE_TOUCHSCREEN)
4163 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004164 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004165 .build()));
4166 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4167 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4168
4169 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4170 // to send a new gesture. It should again go to both windows (spy and the window below), just
4171 // like the first gesture did, before pilfering. The window configuration has not changed.
4172
4173 // One more tap - DOWN
4174 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004175 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004176 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4177 AINPUT_SOURCE_TOUCHSCREEN)
4178 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004179 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004180 .build()));
4181 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4182 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4183 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4184 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4185
4186 // Touch UP on the window
4187 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004188 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004189 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4190 AINPUT_SOURCE_TOUCHSCREEN)
4191 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004192 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004193 .build()));
4194 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4195 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4196 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4197 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4198
4199 window->assertNoEvents();
4200 spyWindow->assertNoEvents();
4201}
4202
Garfield Tandf26e862020-07-01 20:18:19 -07004203// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
4204// directly in this test.
4205TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004206 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07004207 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004208 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004209 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004210
4211 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4212
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004213 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004214
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004215 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004216 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004217 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4218 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004219 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004220 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004221 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004222 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004223 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004224 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004225 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4226 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004227 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004228 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004229 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4230 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004231
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004232 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004233 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004234 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4235 AINPUT_SOURCE_MOUSE)
4236 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4237 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004238 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004239 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004240 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004241
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004242 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004243 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004244 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4245 AINPUT_SOURCE_MOUSE)
4246 .buttonState(0)
4247 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004248 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004249 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004250 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004251
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004252 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004253 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004254 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4255 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004256 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004257 .build()));
4258 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
4259
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07004260 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
4261 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
4262 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004263 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004264 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
4265 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004266 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004267 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004268 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004269}
4270
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004271/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004272 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
4273 * is generated.
4274 */
4275TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
4276 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4277 sp<FakeWindowHandle> window =
4278 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4279 window->setFrame(Rect(0, 0, 1200, 800));
4280
4281 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4282
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004283 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004284
4285 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004286 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004287 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4288 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004289 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004290 .build()));
4291 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4292
4293 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004294 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004295 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4296}
4297
4298/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004299 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4300 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004301TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4302 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4303 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004304 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4305 sp<FakeWindowHandle> window =
4306 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4307 window->setFrame(Rect(0, 0, 1200, 800));
4308
4309 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4310
4311 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4312
4313 MotionEventBuilder hoverEnterBuilder =
4314 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4315 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4316 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4317 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4318 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4319 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4320 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4321 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4322 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4323}
4324
4325/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004326 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4327 */
4328TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4329 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4330 sp<FakeWindowHandle> window =
4331 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4332 window->setFrame(Rect(0, 0, 100, 100));
4333
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004334 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004335
4336 const int32_t mouseDeviceId = 7;
4337 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004338
4339 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004340 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4341 .deviceId(mouseDeviceId)
4342 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4343 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004344 window->consumeMotionEvent(
4345 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4346
4347 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004348 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4349 .deviceId(touchDeviceId)
4350 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4351 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004352
4353 window->consumeMotionEvent(
4354 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4355 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4356}
4357
4358/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004359 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004360 * The tap causes a HOVER_EXIT event to be generated because the current event
4361 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004362 */
4363TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4364 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4365 sp<FakeWindowHandle> window =
4366 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4367 window->setFrame(Rect(0, 0, 100, 100));
4368
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004369 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004370 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4371 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4372 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004373 ASSERT_NO_FATAL_FAILURE(
4374 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4375 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004376
4377 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004378 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4379 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4380 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004381 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004382 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4383 WithSource(AINPUT_SOURCE_MOUSE))));
4384
4385 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004386 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4387 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4388
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004389 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4390 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4391 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004392 ASSERT_NO_FATAL_FAILURE(
4393 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4394 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4395}
4396
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004397TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4398 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4399 sp<FakeWindowHandle> windowDefaultDisplay =
4400 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4401 ADISPLAY_ID_DEFAULT);
4402 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4403 sp<FakeWindowHandle> windowSecondDisplay =
4404 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4405 SECOND_DISPLAY_ID);
4406 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4407
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004408 mDispatcher->onWindowInfosChanged(
4409 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004410
4411 // Set cursor position in window in default display and check that hover enter and move
4412 // events are generated.
4413 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004414 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004415 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4416 AINPUT_SOURCE_MOUSE)
4417 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004418 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004419 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004420 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004421
4422 // Remove all windows in secondary display and check that no event happens on window in
4423 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004424 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4425
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004426 windowDefaultDisplay->assertNoEvents();
4427
4428 // Move cursor position in window in default display and check that only hover move
4429 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004430 mDispatcher->onWindowInfosChanged(
4431 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004432 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004433 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004434 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4435 AINPUT_SOURCE_MOUSE)
4436 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004437 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004438 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004439 windowDefaultDisplay->consumeMotionEvent(
4440 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4441 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004442 windowDefaultDisplay->assertNoEvents();
4443}
4444
Garfield Tan00f511d2019-06-12 16:55:40 -07004445TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004446 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004447
4448 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004449 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004450 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004451 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004452 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004453 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004454
4455 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4456
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004457 mDispatcher->onWindowInfosChanged(
4458 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004459
4460 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4461 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004462 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004463 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004464 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004465 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004466 windowRight->assertNoEvents();
4467}
4468
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004469TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004470 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004471 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4472 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004473 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004474
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004475 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004476 setFocusedWindow(window);
4477
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004478 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004479
Prabir Pradhan678438e2023-04-13 19:32:51 +00004480 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004481
4482 // Window should receive key down event.
4483 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4484
4485 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4486 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004487 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004488 window->consumeKeyUp(ADISPLAY_ID_DEFAULT, AKEY_EVENT_FLAG_CANCELED);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004489}
4490
4491TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004492 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004493 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4494 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004495
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004496 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004497
Prabir Pradhan678438e2023-04-13 19:32:51 +00004498 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4499 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004500
4501 // Window should receive motion down event.
4502 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4503
4504 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4505 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004506 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004507 window->consumeMotionEvent(
4508 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004509}
4510
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004511TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4512 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4513 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4514 "Fake Window", ADISPLAY_ID_DEFAULT);
4515
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004516 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004517
4518 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4519 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4520 .build());
4521
4522 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4523
4524 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4525 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4526 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4527
4528 // After the device has been reset, a new hovering stream can be sent to the window
4529 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4530 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4531 .build());
4532 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4533}
4534
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004535TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4536 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004537 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4538 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004539 window->setFocusable(true);
4540
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004541 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004542 setFocusedWindow(window);
4543
4544 window->consumeFocusEvent(true);
4545
Prabir Pradhan678438e2023-04-13 19:32:51 +00004546 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004547 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4548 const nsecs_t injectTime = keyArgs.eventTime;
4549 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004550 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004551 // The dispatching time should be always greater than or equal to intercept key timeout.
4552 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4553 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4554 std::chrono::nanoseconds(interceptKeyTimeout).count());
4555}
4556
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004557/**
4558 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4559 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004560TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4561 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004562 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4563 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004564 window->setFocusable(true);
4565
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004566 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004567 setFocusedWindow(window);
4568
4569 window->consumeFocusEvent(true);
4570
Prabir Pradhan678438e2023-04-13 19:32:51 +00004571 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004572 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004573
4574 // Set a value that's significantly larger than the default consumption timeout. If the
4575 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4576 mFakePolicy->setInterceptKeyTimeout(600ms);
4577 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4578 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004579 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4580}
4581
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004582/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004583 * Two windows. First is a regular window. Second does not overlap with the first, and has
4584 * WATCH_OUTSIDE_TOUCH.
4585 * Both windows are owned by the same UID.
4586 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4587 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4588 */
4589TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4590 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004591 sp<FakeWindowHandle> window =
4592 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004593 window->setFrame(Rect{0, 0, 100, 100});
4594
4595 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004596 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004597 ADISPLAY_ID_DEFAULT);
4598 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4599 outsideWindow->setWatchOutsideTouch(true);
4600 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004601 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004602
4603 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004604 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4605 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4606 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004607 window->consumeMotionDown();
4608 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4609 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4610 outsideWindow->consumeMotionEvent(
4611 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00004612
4613 // Ensure outsideWindow doesn't get any more events for the gesture.
4614 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4615 ADISPLAY_ID_DEFAULT, {PointF{51, 51}}));
4616 window->consumeMotionMove();
4617 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004618}
4619
4620/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004621 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4622 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4623 * ACTION_OUTSIDE event is sent per gesture.
4624 */
4625TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4626 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4627 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004628 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4629 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004630 window->setWatchOutsideTouch(true);
4631 window->setFrame(Rect{0, 0, 100, 100});
4632 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004633 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4634 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004635 secondWindow->setFrame(Rect{100, 100, 200, 200});
4636 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004637 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4638 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004639 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004640 mDispatcher->onWindowInfosChanged(
4641 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004642
4643 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004644 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4645 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4646 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004647 window->assertNoEvents();
4648 secondWindow->assertNoEvents();
4649
4650 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4651 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004652 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4653 ADISPLAY_ID_DEFAULT,
4654 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004655 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4656 window->consumeMotionEvent(
4657 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004658 secondWindow->consumeMotionDown();
4659 thirdWindow->assertNoEvents();
4660
4661 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4662 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004663 mDispatcher->notifyMotion(
4664 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4665 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004666 window->assertNoEvents();
4667 secondWindow->consumeMotionMove();
4668 thirdWindow->consumeMotionDown();
4669}
4670
Prabir Pradhan814fe082022-07-22 20:22:18 +00004671TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4672 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004673 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4674 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004675 window->setFocusable(true);
4676
Patrick Williamsd828f302023-04-28 17:52:08 -05004677 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004678 setFocusedWindow(window);
4679
4680 window->consumeFocusEvent(true);
4681
Prabir Pradhan678438e2023-04-13 19:32:51 +00004682 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4683 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4684 mDispatcher->notifyKey(keyDown);
4685 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004686
4687 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4688 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4689
4690 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004691 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004692
4693 window->consumeFocusEvent(false);
4694
Prabir Pradhan678438e2023-04-13 19:32:51 +00004695 mDispatcher->notifyKey(keyDown);
4696 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004697 window->assertNoEvents();
4698}
4699
Arthur Hung96483742022-11-15 03:30:48 +00004700TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4701 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4702 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4703 "Fake Window", ADISPLAY_ID_DEFAULT);
4704 // Ensure window is non-split and have some transform.
4705 window->setPreventSplitting(true);
4706 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004707 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004708
4709 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004710 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004711 {50, 50}))
4712 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4713 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4714
4715 const MotionEvent secondFingerDownEvent =
4716 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4717 .displayId(ADISPLAY_ID_DEFAULT)
4718 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004719 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4720 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004721 .build();
4722 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004723 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004724 InputEventInjectionSync::WAIT_FOR_RESULT))
4725 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4726
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004727 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
4728 ASSERT_NE(nullptr, event);
4729 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4730 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4731 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4732 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4733 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
Arthur Hung96483742022-11-15 03:30:48 +00004734}
4735
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004736/**
4737 * Two windows: a splittable and a non-splittable.
4738 * The non-splittable window shouldn't receive any "incomplete" gestures.
4739 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4740 * The second pointer should be dropped because the initial window is splittable, so it won't get
4741 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4742 * "incomplete" gestures.
4743 */
4744TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4745 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4746 sp<FakeWindowHandle> leftWindow =
4747 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4748 ADISPLAY_ID_DEFAULT);
4749 leftWindow->setPreventSplitting(false);
4750 leftWindow->setFrame(Rect(0, 0, 100, 100));
4751 sp<FakeWindowHandle> rightWindow =
4752 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4753 ADISPLAY_ID_DEFAULT);
4754 rightWindow->setPreventSplitting(true);
4755 rightWindow->setFrame(Rect(100, 100, 200, 200));
4756 mDispatcher->onWindowInfosChanged(
4757 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4758
4759 // Touch down on left, splittable window
4760 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4761 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4762 .build());
4763 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4764
4765 mDispatcher->notifyMotion(
4766 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4767 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4768 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4769 .build());
4770 leftWindow->assertNoEvents();
4771 rightWindow->assertNoEvents();
4772}
4773
Harry Cuttsb166c002023-05-09 13:06:05 +00004774TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4775 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4776 sp<FakeWindowHandle> window =
4777 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4778 window->setFrame(Rect(0, 0, 400, 400));
4779 sp<FakeWindowHandle> trustedOverlay =
4780 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4781 ADISPLAY_ID_DEFAULT);
4782 trustedOverlay->setSpy(true);
4783 trustedOverlay->setTrustedOverlay(true);
4784
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004785 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004786
4787 // Start a three-finger touchpad swipe
4788 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4789 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4790 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4791 .build());
4792 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4793 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4794 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4795 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4796 .build());
4797 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4798 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4799 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4800 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4801 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4802 .build());
4803
4804 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4805 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4806 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4807
4808 // Move the swipe a bit
4809 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4810 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4811 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4812 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4813 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4814 .build());
4815
4816 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4817
4818 // End the swipe
4819 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4820 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4821 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4822 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4823 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4824 .build());
4825 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4826 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4827 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4828 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4829 .build());
4830 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4831 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4832 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4833 .build());
4834
4835 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4836 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4837 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4838
4839 window->assertNoEvents();
4840}
4841
4842TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4843 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4844 sp<FakeWindowHandle> window =
4845 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4846 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004847 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004848
4849 // Start a three-finger touchpad swipe
4850 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4851 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4852 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4853 .build());
4854 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4855 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4856 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4857 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4858 .build());
4859 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4860 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4861 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4862 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4863 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4864 .build());
4865
4866 // Move the swipe a bit
4867 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4868 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4869 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4870 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4871 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4872 .build());
4873
4874 // End the swipe
4875 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4876 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4877 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4878 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4879 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4880 .build());
4881 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4882 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4883 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4884 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4885 .build());
4886 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4887 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4888 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4889 .build());
4890
4891 window->assertNoEvents();
4892}
4893
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004894/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004895 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4896 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004897 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004898 */
4899TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4900 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4901 sp<FakeWindowHandle> window =
4902 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4903 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004904 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004905
4906 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4907 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4908 .downTime(baseTime + 10)
4909 .eventTime(baseTime + 10)
4910 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4911 .build());
4912
4913 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4914
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004915 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004916 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004917
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004918 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004919
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004920 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4921 .downTime(baseTime + 10)
4922 .eventTime(baseTime + 30)
4923 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4924 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4925 .build());
4926
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004927 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4928
4929 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004930 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4931 .downTime(baseTime + 10)
4932 .eventTime(baseTime + 40)
4933 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4934 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4935 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004936
4937 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4938
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004939 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4940 .downTime(baseTime + 10)
4941 .eventTime(baseTime + 50)
4942 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4943 .build());
4944
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004945 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4946
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004947 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4948 .downTime(baseTime + 60)
4949 .eventTime(baseTime + 60)
4950 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4951 .build());
4952
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004953 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004954}
4955
4956/**
Hu Guo771a7692023-09-17 20:51:08 +08004957 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4958 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4959 * its coordinates should be converted by the transform of the windows of target screen.
4960 */
4961TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4962 // This case will create a window and a spy window on the default display and mirror
4963 // window on the second display. cancel event is sent through spy window pilferPointers
4964 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4965
4966 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4967 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4968 spyWindowDefaultDisplay->setTrustedOverlay(true);
4969 spyWindowDefaultDisplay->setSpy(true);
4970
4971 sp<FakeWindowHandle> windowDefaultDisplay =
4972 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4973 ADISPLAY_ID_DEFAULT);
4974 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4975
4976 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4977 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4978
4979 // Add the windows to the dispatcher
4980 mDispatcher->onWindowInfosChanged(
4981 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4982 *windowSecondDisplay->getInfo()},
4983 {},
4984 0,
4985 0});
4986
4987 // Send down to ADISPLAY_ID_DEFAULT
4988 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4989 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4990 {100, 100}))
4991 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4992
4993 spyWindowDefaultDisplay->consumeMotionDown();
4994 windowDefaultDisplay->consumeMotionDown();
4995
4996 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4997
4998 // windowDefaultDisplay gets cancel
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004999 std::unique_ptr<MotionEvent> event = windowDefaultDisplay->consumeMotionEvent();
5000 ASSERT_NE(nullptr, event);
5001 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
Hu Guo771a7692023-09-17 20:51:08 +08005002
5003 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
5004 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
5005 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
5006 // SECOND_DISPLAY_ID, the x and y coordinates are 200
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005007 EXPECT_EQ(100, event->getX(0));
5008 EXPECT_EQ(100, event->getY(0));
Hu Guo771a7692023-09-17 20:51:08 +08005009}
5010
5011/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005012 * Ensure the correct coordinate spaces are used by InputDispatcher.
5013 *
5014 * InputDispatcher works in the display space, so its coordinate system is relative to the display
5015 * panel. Windows get events in the window space, and get raw coordinates in the logical display
5016 * space.
5017 */
5018class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
5019public:
5020 void SetUp() override {
5021 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005022 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005023 }
5024
5025 void addDisplayInfo(int displayId, const ui::Transform& transform) {
5026 gui::DisplayInfo info;
5027 info.displayId = displayId;
5028 info.transform = transform;
5029 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05005030 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005031 }
5032
5033 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
5034 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05005035 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005036 }
5037
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005038 void removeAllWindowsAndDisplays() {
5039 mDisplayInfos.clear();
5040 mWindowInfos.clear();
5041 }
5042
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005043 // Set up a test scenario where the display has a scaled projection and there are two windows
5044 // on the display.
5045 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
5046 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
5047 // respectively.
5048 ui::Transform displayTransform;
5049 displayTransform.set(2, 0, 0, 4);
5050 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5051
5052 std::shared_ptr<FakeApplicationHandle> application =
5053 std::make_shared<FakeApplicationHandle>();
5054
5055 // Add two windows to the display. Their frames are represented in the display space.
5056 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005057 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5058 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005059 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
5060 addWindow(firstWindow);
5061
5062 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005063 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5064 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005065 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
5066 addWindow(secondWindow);
5067 return {std::move(firstWindow), std::move(secondWindow)};
5068 }
5069
5070private:
5071 std::vector<gui::DisplayInfo> mDisplayInfos;
5072 std::vector<gui::WindowInfo> mWindowInfos;
5073};
5074
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005075TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005076 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5077 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005078 // selected so that if the hit test was performed with the point and the bounds being in
5079 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005080 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5081 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5082 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005083
5084 firstWindow->consumeMotionDown();
5085 secondWindow->assertNoEvents();
5086}
5087
5088// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
5089// the event should be treated as being in the logical display space.
5090TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
5091 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5092 // Send down to the first window. The point is represented in the logical display space. The
5093 // point is selected so that if the hit test was done in logical display space, then it would
5094 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005095 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005096 PointF{75 * 2, 55 * 4});
5097
5098 firstWindow->consumeMotionDown();
5099 secondWindow->assertNoEvents();
5100}
5101
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005102// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
5103// event should be treated as being in the logical display space.
5104TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
5105 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5106
5107 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5108 ui::Transform injectedEventTransform;
5109 injectedEventTransform.set(matrix);
5110 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
5111 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
5112
5113 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5114 .displayId(ADISPLAY_ID_DEFAULT)
5115 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005116 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005117 .x(untransformedPoint.x)
5118 .y(untransformedPoint.y))
5119 .build();
5120 event.transform(matrix);
5121
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005122 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005123 InputEventInjectionSync::WAIT_FOR_RESULT);
5124
5125 firstWindow->consumeMotionDown();
5126 secondWindow->assertNoEvents();
5127}
5128
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005129TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
5130 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5131
5132 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005133 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5134 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5135 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005136
5137 firstWindow->assertNoEvents();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005138 std::unique_ptr<MotionEvent> event = secondWindow->consumeMotionEvent();
5139 ASSERT_NE(nullptr, event);
5140 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005141
5142 // Ensure that the events from the "getRaw" API are in logical display coordinates.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005143 EXPECT_EQ(300, event->getRawX(0));
5144 EXPECT_EQ(880, event->getRawY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005145
5146 // Ensure that the x and y values are in the window's coordinate space.
5147 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
5148 // the logical display space. This will be the origin of the window space.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005149 EXPECT_EQ(100, event->getX(0));
5150 EXPECT_EQ(80, event->getY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005151}
5152
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005153TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
5154 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5155 // The monitor will always receive events in the logical display's coordinate space, because
5156 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00005157 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005158
5159 // Send down to the first window.
5160 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5161 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5162 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5163 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5164
5165 // Second pointer goes down on second window.
5166 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5167 ADISPLAY_ID_DEFAULT,
5168 {PointF{50, 100}, PointF{150, 220}}));
5169 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
5170 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
5171 {1, PointF{300, 880}}};
5172 monitor.consumeMotionEvent(
5173 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
5174
5175 mDispatcher->cancelCurrentTouch();
5176
5177 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5178 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
5179 monitor.consumeMotionEvent(
5180 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
5181}
5182
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005183TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
5184 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5185
5186 // Send down to the first window.
5187 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5188 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5189 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5190
5191 // The pointer is transferred to the second window, and the second window receives it in the
5192 // correct coordinate space.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005193 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005194 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5195 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
5196}
5197
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005198TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
5199 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5200
5201 // Send hover move to the second window, and ensure it shows up as hover enter.
5202 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5203 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5204 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5205 WithCoords(100, 80), WithRawCoords(300, 880)));
5206
5207 // Touch down at the same location and ensure a hover exit is synthesized.
5208 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5209 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5210 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5211 WithRawCoords(300, 880)));
5212 secondWindow->consumeMotionEvent(
5213 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5214 secondWindow->assertNoEvents();
5215 firstWindow->assertNoEvents();
5216}
5217
Prabir Pradhan453ae732023-10-13 14:30:14 +00005218// Same as above, but while the window is being mirrored.
5219TEST_F(InputDispatcherDisplayProjectionTest,
5220 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
5221 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5222
5223 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5224 ui::Transform secondDisplayTransform;
5225 secondDisplayTransform.set(matrix);
5226 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5227
5228 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5229 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5230 addWindow(secondWindowClone);
5231
5232 // Send hover move to the second window, and ensure it shows up as hover enter.
5233 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5234 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5235 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5236 WithCoords(100, 80), WithRawCoords(300, 880)));
5237
5238 // Touch down at the same location and ensure a hover exit is synthesized for the correct
5239 // display.
5240 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5241 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5242 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5243 WithRawCoords(300, 880)));
5244 secondWindow->consumeMotionEvent(
5245 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5246 secondWindow->assertNoEvents();
5247 firstWindow->assertNoEvents();
5248}
5249
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005250TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
5251 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5252
5253 // Send hover enter to second window
5254 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5255 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5256 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5257 WithCoords(100, 80), WithRawCoords(300, 880)));
5258
5259 mDispatcher->cancelCurrentTouch();
5260
5261 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5262 WithRawCoords(300, 880)));
5263 secondWindow->assertNoEvents();
5264 firstWindow->assertNoEvents();
5265}
5266
Prabir Pradhan453ae732023-10-13 14:30:14 +00005267// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00005268TEST_F(InputDispatcherDisplayProjectionTest,
5269 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
5270 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5271
5272 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5273 ui::Transform secondDisplayTransform;
5274 secondDisplayTransform.set(matrix);
5275 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5276
5277 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5278 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5279 addWindow(secondWindowClone);
5280
5281 // Send hover enter to second window
5282 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, 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 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5287
5288 mDispatcher->cancelCurrentTouch();
5289
5290 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
5291 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5292 WithRawCoords(300, 880),
5293 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5294 secondWindow->assertNoEvents();
5295 firstWindow->assertNoEvents();
5296}
5297
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005298/** Ensure consistent behavior of InputDispatcher in all orientations. */
5299class InputDispatcherDisplayOrientationFixture
5300 : public InputDispatcherDisplayProjectionTest,
5301 public ::testing::WithParamInterface<ui::Rotation> {};
5302
5303// This test verifies the touchable region of a window for all rotations of the display by tapping
5304// in different locations on the display, specifically points close to the four corners of a
5305// window.
5306TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
5307 constexpr static int32_t displayWidth = 400;
5308 constexpr static int32_t displayHeight = 800;
5309
5310 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5311
5312 const auto rotation = GetParam();
5313
5314 // Set up the display with the specified rotation.
5315 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5316 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5317 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5318 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5319 logicalDisplayWidth, logicalDisplayHeight);
5320 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5321
5322 // Create a window with its bounds determined in the logical display.
5323 const Rect frameInLogicalDisplay(100, 100, 200, 300);
5324 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
5325 sp<FakeWindowHandle> window =
5326 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5327 window->setFrame(frameInDisplay, displayTransform);
5328 addWindow(window);
5329
5330 // The following points in logical display space should be inside the window.
5331 static const std::array<vec2, 4> insidePoints{
5332 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5333 for (const auto pointInsideWindow : insidePoints) {
5334 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
5335 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005336 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5337 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5338 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005339 window->consumeMotionDown();
5340
Prabir Pradhan678438e2023-04-13 19:32:51 +00005341 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5342 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5343 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005344 window->consumeMotionUp();
5345 }
5346
5347 // The following points in logical display space should be outside the window.
5348 static const std::array<vec2, 5> outsidePoints{
5349 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
5350 for (const auto pointOutsideWindow : outsidePoints) {
5351 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
5352 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005353 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5354 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5355 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005356
Prabir Pradhan678438e2023-04-13 19:32:51 +00005357 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5358 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5359 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005360 }
5361 window->assertNoEvents();
5362}
5363
5364// Run the precision tests for all rotations.
5365INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
5366 InputDispatcherDisplayOrientationFixture,
5367 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
5368 ui::ROTATION_270),
5369 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
5370 return ftl::enum_string(testParamInfo.param);
5371 });
5372
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005373using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
5374 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005375
5376class TransferTouchFixture : public InputDispatcherTest,
5377 public ::testing::WithParamInterface<TransferFunction> {};
5378
5379TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07005380 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005381
5382 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005383 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005384 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5385 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005386 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005387 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005388 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5389 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005390 sp<FakeWindowHandle> wallpaper =
5391 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
5392 wallpaper->setIsWallpaper(true);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005393 // Add the windows to the dispatcher, and ensure the first window is focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005394 mDispatcher->onWindowInfosChanged(
5395 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Prabir Pradhan65455c72024-02-13 21:46:41 +00005396 setFocusedWindow(firstWindow);
5397 firstWindow->consumeFocusEvent(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005398
5399 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005400 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5401 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005402
Svet Ganov5d3bc372020-01-26 23:11:07 -08005403 // Only the first window should get the down event
5404 firstWindow->consumeMotionDown();
5405 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005406 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005407 // Dispatcher reports pointer down outside focus for the wallpaper
5408 mFakePolicy->assertOnPointerDownEquals(wallpaper->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08005409
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005410 // Transfer touch to the second window
5411 TransferFunction f = GetParam();
5412 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5413 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005414 // The first window gets cancel and the second gets down
5415 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005416 secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005417 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005418 // There should not be any changes to the focused window when transferring touch
5419 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertOnPointerDownWasNotCalled());
Svet Ganov5d3bc372020-01-26 23:11:07 -08005420
5421 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005422 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5423 ADISPLAY_ID_DEFAULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +00005424 // The first window gets no events and the second gets up
Svet Ganov5d3bc372020-01-26 23:11:07 -08005425 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005426 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005427 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005428}
5429
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005430/**
Prabir Pradhan367f3432024-02-13 23:05:58 +00005431 * When 'transferTouchGesture' API is invoked, dispatcher needs to find the "best" window to take
5432 * touch from. When we have spy windows, there are several windows to choose from: either spy, or
5433 * the 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005434 * natural to the user.
5435 * In this test, we are sending a pointer to both spy window and first window. We then try to
5436 * transfer touch to the second window. The dispatcher should identify the first window as the
5437 * one that should lose the gesture, and therefore the action should be to move the gesture from
5438 * the first window to the second.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005439 * The main goal here is to test the behaviour of 'transferTouchGesture' API, but it's still valid
5440 * to test the other API, as well.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005441 */
5442TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5443 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5444
5445 // Create a couple of windows + a spy window
5446 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005447 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005448 spyWindow->setTrustedOverlay(true);
5449 spyWindow->setSpy(true);
5450 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005451 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005452 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005453 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005454
5455 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005456 mDispatcher->onWindowInfosChanged(
5457 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005458
5459 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005460 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5461 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005462 // Only the first window and spy should get the down event
5463 spyWindow->consumeMotionDown();
5464 firstWindow->consumeMotionDown();
5465
5466 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
Prabir Pradhan367f3432024-02-13 23:05:58 +00005467 // if f === 'transferTouchGesture'.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005468 TransferFunction f = GetParam();
5469 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5470 ASSERT_TRUE(success);
5471 // The first window gets cancel and the second gets down
5472 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005473 secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005474
5475 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005476 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5477 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005478 // The first window gets no events and the second+spy get up
5479 firstWindow->assertNoEvents();
5480 spyWindow->consumeMotionUp();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005481 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005482}
5483
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005484TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005485 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005486
5487 PointF touchPoint = {10, 10};
5488
5489 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005490 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005491 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5492 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005493 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005494 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005495 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5496 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005497 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005498
5499 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005500 mDispatcher->onWindowInfosChanged(
5501 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005502
5503 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005504 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5505 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5506 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005507 // Only the first window should get the down event
5508 firstWindow->consumeMotionDown();
5509 secondWindow->assertNoEvents();
5510
5511 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005512 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5513 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005514 // Only the first window should get the pointer down event
5515 firstWindow->consumeMotionPointerDown(1);
5516 secondWindow->assertNoEvents();
5517
5518 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005519 TransferFunction f = GetParam();
5520 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5521 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005522 // The first window gets cancel and the second gets down and pointer down
5523 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005524 secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
5525 secondWindow->consumeMotionPointerDown(1, ADISPLAY_ID_DEFAULT,
5526 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005527
5528 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005529 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5530 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005531 // The first window gets nothing and the second gets pointer up
5532 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005533 secondWindow->consumeMotionPointerUp(1, ADISPLAY_ID_DEFAULT,
5534 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005535
5536 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005537 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5538 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005539 // The first window gets nothing and the second gets up
5540 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005541 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005542}
5543
Arthur Hungc539dbb2022-12-08 07:45:36 +00005544TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5545 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5546
5547 // Create a couple of windows
5548 sp<FakeWindowHandle> firstWindow =
5549 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5550 ADISPLAY_ID_DEFAULT);
5551 firstWindow->setDupTouchToWallpaper(true);
5552 sp<FakeWindowHandle> secondWindow =
5553 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5554 ADISPLAY_ID_DEFAULT);
5555 secondWindow->setDupTouchToWallpaper(true);
5556
5557 sp<FakeWindowHandle> wallpaper1 =
5558 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5559 wallpaper1->setIsWallpaper(true);
5560
5561 sp<FakeWindowHandle> wallpaper2 =
5562 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5563 wallpaper2->setIsWallpaper(true);
5564 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005565 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5566 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5567 {},
5568 0,
5569 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005570
5571 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005572 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5573 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005574
5575 // Only the first window should get the down event
5576 firstWindow->consumeMotionDown();
5577 secondWindow->assertNoEvents();
5578 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5579 wallpaper2->assertNoEvents();
5580
5581 // Transfer touch focus to the second window
5582 TransferFunction f = GetParam();
5583 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5584 ASSERT_TRUE(success);
5585
5586 // The first window gets cancel and the second gets down
5587 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005588 secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005589 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005590 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5591 expectedWallpaperFlags | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005592
5593 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005594 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5595 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005596 // The first window gets no events and the second gets up
5597 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005598 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005599 wallpaper1->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005600 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT,
5601 expectedWallpaperFlags | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005602}
5603
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005604// For the cases of single pointer touch and two pointers non-split touch, the api's
Prabir Pradhan367f3432024-02-13 23:05:58 +00005605// 'transferTouchGesture' and 'transferTouchOnDisplay' are equivalent in behaviour. They only differ
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005606// for the case where there are multiple pointers split across several windows.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005607INSTANTIATE_TEST_SUITE_P(
5608 InputDispatcherTransferFunctionTests, TransferTouchFixture,
5609 ::testing::Values(
5610 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> /*ignored*/,
5611 sp<IBinder> destChannelToken) {
5612 return dispatcher->transferTouchOnDisplay(destChannelToken,
5613 ADISPLAY_ID_DEFAULT);
5614 },
5615 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> from,
5616 sp<IBinder> to) {
5617 return dispatcher->transferTouchGesture(from, to,
5618 /*isDragAndDrop=*/false);
5619 }));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005620
Prabir Pradhan367f3432024-02-13 23:05:58 +00005621TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005622 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005623
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005624 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005625 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5626 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005627 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005628
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005629 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005630 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5631 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005632 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005633
5634 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005635 mDispatcher->onWindowInfosChanged(
5636 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005637
5638 PointF pointInFirst = {300, 200};
5639 PointF pointInSecond = {300, 600};
5640
5641 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005642 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5643 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5644 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005645 // Only the first window should get the down event
5646 firstWindow->consumeMotionDown();
5647 secondWindow->assertNoEvents();
5648
5649 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005650 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5651 ADISPLAY_ID_DEFAULT,
5652 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005653 // The first window gets a move and the second a down
5654 firstWindow->consumeMotionMove();
5655 secondWindow->consumeMotionDown();
5656
Prabir Pradhan367f3432024-02-13 23:05:58 +00005657 // Transfer touch to the second window
5658 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08005659 // The first window gets cancel and the new gets pointer down (it already saw down)
5660 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005661 secondWindow->consumeMotionPointerDown(1, ADISPLAY_ID_DEFAULT,
5662 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005663
5664 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005665 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5666 ADISPLAY_ID_DEFAULT,
5667 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005668 // The first window gets nothing and the second gets pointer up
5669 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005670 secondWindow->consumeMotionPointerUp(1, ADISPLAY_ID_DEFAULT,
5671 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005672
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));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005676 // The first window gets nothing 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);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005679}
5680
Prabir Pradhan367f3432024-02-13 23:05:58 +00005681// Same as TransferTouch_TwoPointersSplitTouch, but using 'transferTouchOnDisplay' api.
5682// Unlike 'transferTouchGesture', calling 'transferTouchOnDisplay' when there are two windows
5683// receiving touch is not supported, so the touch should continue on those windows and the
5684// transferred-to window should get nothing.
5685TEST_F(InputDispatcherTest, TransferTouchOnDisplay_TwoPointersSplitTouch) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005686 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5687
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005688 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005689 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5690 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005691 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005692
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005693 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005694 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5695 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005696 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005697
5698 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005699 mDispatcher->onWindowInfosChanged(
5700 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005701
5702 PointF pointInFirst = {300, 200};
5703 PointF pointInSecond = {300, 600};
5704
5705 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005706 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5707 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5708 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005709 // Only the first window should get the down event
5710 firstWindow->consumeMotionDown();
5711 secondWindow->assertNoEvents();
5712
5713 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005714 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5715 ADISPLAY_ID_DEFAULT,
5716 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005717 // The first window gets a move and the second a down
5718 firstWindow->consumeMotionMove();
5719 secondWindow->consumeMotionDown();
5720
5721 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005722 const bool transferred =
Prabir Pradhan367f3432024-02-13 23:05:58 +00005723 mDispatcher->transferTouchOnDisplay(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
5724 // The 'transferTouchOnDisplay' call should not succeed, because there are 2 touched windows
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005725 ASSERT_FALSE(transferred);
5726 firstWindow->assertNoEvents();
5727 secondWindow->assertNoEvents();
5728
5729 // The rest of the dispatch should proceed as normal
5730 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005731 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5732 ADISPLAY_ID_DEFAULT,
5733 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005734 // The first window gets MOVE and the second gets pointer up
5735 firstWindow->consumeMotionMove();
5736 secondWindow->consumeMotionUp();
5737
5738 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005739 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5740 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005741 // The first window gets nothing and the second gets up
5742 firstWindow->consumeMotionUp();
5743 secondWindow->assertNoEvents();
5744}
5745
Arthur Hungabbb9d82021-09-01 14:52:30 +00005746// This case will create two windows and one mirrored window on the default display and mirror
Prabir Pradhan367f3432024-02-13 23:05:58 +00005747// two windows on the second display. It will test if 'transferTouchGesture' works fine if we put
Arthur Hungabbb9d82021-09-01 14:52:30 +00005748// the windows info of second display before default display.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005749TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00005750 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5751 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005752 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005753 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005754 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005755 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005756 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005757
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005758 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005759 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005760
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005761 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005762 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005763
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005764 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005765 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005766
5767 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005768 mDispatcher->onWindowInfosChanged(
5769 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5770 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5771 *secondWindowInPrimary->getInfo()},
5772 {},
5773 0,
5774 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005775
5776 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005777 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005778 {50, 50}))
5779 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5780
5781 // Window should receive motion event.
5782 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5783
Prabir Pradhan367f3432024-02-13 23:05:58 +00005784 // Transfer touch
5785 ASSERT_TRUE(mDispatcher->transferTouchGesture(firstWindowInPrimary->getToken(),
5786 secondWindowInPrimary->getToken()));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005787 // The first window gets cancel.
5788 firstWindowInPrimary->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005789 secondWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5790 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005791
5792 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005793 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005794 ADISPLAY_ID_DEFAULT, {150, 50}))
5795 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5796 firstWindowInPrimary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005797 secondWindowInPrimary->consumeMotionMove(ADISPLAY_ID_DEFAULT,
5798 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005799
5800 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005801 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005802 {150, 50}))
5803 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5804 firstWindowInPrimary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005805 secondWindowInPrimary->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005806}
5807
Prabir Pradhan367f3432024-02-13 23:05:58 +00005808// Same as TransferTouch_CloneSurface, but this touch on the secondary display and use
5809// 'transferTouchOnDisplay' api.
5810TEST_F(InputDispatcherTest, TransferTouchOnDisplay_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00005811 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5812 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005813 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005814 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005815 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005816 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005817 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005818
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005819 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005820 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005821
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005822 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005823 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005824
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005825 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005826 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005827
5828 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005829 mDispatcher->onWindowInfosChanged(
5830 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5831 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5832 *secondWindowInPrimary->getInfo()},
5833 {},
5834 0,
5835 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005836
5837 // Touch on second display.
5838 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005839 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5840 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005841 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5842
5843 // Window should receive motion event.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005844 firstWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005845
5846 // Transfer touch focus
Prabir Pradhan367f3432024-02-13 23:05:58 +00005847 ASSERT_TRUE(mDispatcher->transferTouchOnDisplay(secondWindowInSecondary->getToken(),
5848 SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005849
5850 // The first window gets cancel.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005851 firstWindowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005852 secondWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID,
5853 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005854
5855 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005856 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005857 SECOND_DISPLAY_ID, {150, 50}))
5858 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005859 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005860 secondWindowInSecondary->consumeMotionMove(SECOND_DISPLAY_ID,
5861 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005862
5863 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005864 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005865 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005866 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005867 secondWindowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005868}
5869
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005870TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005871 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005872 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5873 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005874
Vishnu Nair47074b82020-08-14 11:54:47 -07005875 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005876 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005877 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005878
5879 window->consumeFocusEvent(true);
5880
Prabir Pradhan678438e2023-04-13 19:32:51 +00005881 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005882
5883 // Window should receive key down event.
5884 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005885
5886 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005887 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005888 mFakePolicy->assertUserActivityPoked();
5889}
5890
5891TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5892 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5893 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5894 "Fake Window", ADISPLAY_ID_DEFAULT);
5895
5896 window->setDisableUserActivity(true);
5897 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005898 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005899 setFocusedWindow(window);
5900
5901 window->consumeFocusEvent(true);
5902
5903 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5904
5905 // Window should receive key down event.
5906 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5907
5908 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005909 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005910 mFakePolicy->assertUserActivityNotPoked();
5911}
5912
5913TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5914 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5915 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5916 "Fake Window", ADISPLAY_ID_DEFAULT);
5917
5918 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005919 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005920 setFocusedWindow(window);
5921
5922 window->consumeFocusEvent(true);
5923
5924 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5925 mDispatcher->waitForIdle();
5926
5927 // System key is not passed down
5928 window->assertNoEvents();
5929
5930 // Should have poked user activity
5931 mFakePolicy->assertUserActivityPoked();
5932}
5933
5934TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5935 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5936 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5937 "Fake Window", ADISPLAY_ID_DEFAULT);
5938
5939 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005940 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005941 setFocusedWindow(window);
5942
5943 window->consumeFocusEvent(true);
5944
5945 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5946 mDispatcher->waitForIdle();
5947
5948 // System key is not passed down
5949 window->assertNoEvents();
5950
5951 // Should have poked user activity
5952 mFakePolicy->assertUserActivityPoked();
5953}
5954
5955TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5956 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5957 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5958 "Fake Window", ADISPLAY_ID_DEFAULT);
5959
5960 window->setDisableUserActivity(true);
5961 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005962 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005963 setFocusedWindow(window);
5964
5965 window->consumeFocusEvent(true);
5966
5967 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5968 mDispatcher->waitForIdle();
5969
5970 // System key is not passed down
5971 window->assertNoEvents();
5972
5973 // Should have poked user activity
5974 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005975}
5976
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005977TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5978 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5979 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5980 "Fake Window", ADISPLAY_ID_DEFAULT);
5981
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005982 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005983
5984 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005985 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005986 ADISPLAY_ID_DEFAULT, {100, 100}))
5987 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5988
5989 window->consumeMotionEvent(
5990 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5991
5992 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005993 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005994 mFakePolicy->assertUserActivityPoked();
5995}
5996
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005997TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005998 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005999 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6000 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006001
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006002 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006003
Prabir Pradhan678438e2023-04-13 19:32:51 +00006004 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006005 mDispatcher->waitForIdle();
6006
6007 window->assertNoEvents();
6008}
6009
6010// If a window is touchable, but does not have focus, it should receive motion events, but not keys
6011TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07006012 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006013 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6014 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006015
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006016 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006017
6018 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00006019 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006020 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00006021 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6022 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006023
6024 // Window should receive only the motion event
6025 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6026 window->assertNoEvents(); // Key event or focus event will not be received
6027}
6028
arthurhungea3f4fc2020-12-21 23:18:53 +08006029TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
6030 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6031
arthurhungea3f4fc2020-12-21 23:18:53 +08006032 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006033 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
6034 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08006035 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08006036
arthurhungea3f4fc2020-12-21 23:18:53 +08006037 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006038 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
6039 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08006040 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08006041
6042 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006043 mDispatcher->onWindowInfosChanged(
6044 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08006045
6046 PointF pointInFirst = {300, 200};
6047 PointF pointInSecond = {300, 600};
6048
6049 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006050 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6051 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6052 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08006053 // Only the first window should get the down event
6054 firstWindow->consumeMotionDown();
6055 secondWindow->assertNoEvents();
6056
6057 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006058 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6059 ADISPLAY_ID_DEFAULT,
6060 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08006061 // The first window gets a move and the second a down
6062 firstWindow->consumeMotionMove();
6063 secondWindow->consumeMotionDown();
6064
6065 // Send pointer cancel to the second window
6066 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006067 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08006068 {pointInFirst, pointInSecond});
6069 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00006070 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08006071 // The first window gets move and the second gets cancel.
6072 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
6073 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
6074
6075 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00006076 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6077 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08006078 // The first window gets up and the second gets nothing.
6079 firstWindow->consumeMotionUp();
6080 secondWindow->assertNoEvents();
6081}
6082
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006083TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
6084 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6085
6086 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006087 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006088 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006089 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
6090 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
6091 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
6092
Harry Cutts33476232023-01-30 19:57:29 +00006093 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006094 window->assertNoEvents();
6095 mDispatcher->waitForIdle();
6096}
6097
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006098using InputDispatcherMonitorTest = InputDispatcherTest;
6099
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006100/**
6101 * Two entities that receive touch: A window, and a global monitor.
6102 * The touch goes to the window, and then the window disappears.
6103 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
6104 * for the monitor, as well.
6105 * 1. foregroundWindow
6106 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
6107 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006108TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006109 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6110 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006111 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006112
Prabir Pradhanfb549072023-10-05 19:17:36 +00006113 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006114
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006115 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006116 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006117 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006118 {100, 200}))
6119 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6120
6121 // Both the foreground window and the global monitor should receive the touch down
6122 window->consumeMotionDown();
6123 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6124
6125 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006126 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006127 ADISPLAY_ID_DEFAULT, {110, 200}))
6128 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6129
6130 window->consumeMotionMove();
6131 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6132
6133 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006134 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006135 window->consumeMotionCancel();
6136 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
6137
6138 // If more events come in, there will be no more foreground window to send them to. This will
6139 // cause a cancel for the monitor, as well.
6140 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006141 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006142 ADISPLAY_ID_DEFAULT, {120, 200}))
6143 << "Injection should fail because the window was removed";
6144 window->assertNoEvents();
6145 // Global monitor now gets the cancel
6146 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6147}
6148
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006149TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07006150 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006151 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6152 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006153 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006154
Prabir Pradhanfb549072023-10-05 19:17:36 +00006155 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006156
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006157 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006158 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006159 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00006160 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006161 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006162}
6163
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006164TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00006165 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006166
Chris Yea209fde2020-07-22 13:54:51 -07006167 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006168 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6169 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006170 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006171
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006172 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006173 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006174 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08006175 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006176 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006177
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006178 // Pilfer pointers from the monitor.
6179 // This should not do anything and the window should continue to receive events.
6180 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00006181
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006182 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006183 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006184 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006185 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006186
6187 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6188 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006189}
6190
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006191TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07006192 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006193 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6194 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006195 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07006196 window->setWindowOffset(20, 40);
6197 window->setWindowTransform(0, 1, -1, 0);
6198
Prabir Pradhanfb549072023-10-05 19:17:36 +00006199 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07006200
6201 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006202 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07006203 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6204 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006205 std::unique_ptr<MotionEvent> event = monitor.consumeMotion();
6206 ASSERT_NE(nullptr, event);
Evan Rosky84f07f02021-04-16 10:42:42 -07006207 // Even though window has transform, gesture monitor must not.
6208 ASSERT_EQ(ui::Transform(), event->getTransform());
6209}
6210
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006211TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00006212 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00006213 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00006214
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006215 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006216 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006217 << "Injection should fail if there is a monitor, but no touchable window";
6218 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00006219}
6220
Linnan Lid8150952024-01-26 18:07:17 +00006221/**
6222 * Two displays
6223 * The first monitor has a foreground window, a monitor
6224 * The second window has only one monitor.
6225 * We first inject a Down event into the first display, this injection should succeed and both
6226 * the foreground window and monitor should receive a down event, then inject a Down event into
6227 * the second display as well, this injection should fail, at this point, the first display
6228 * window and monitor should not receive a cancel or any other event.
6229 * Continue to inject Move and UP events to the first display, the events should be received
6230 * normally by the foreground window and monitor.
6231 */
6232TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCanceledWhenAnotherEmptyDisplayReceiveEvents) {
6233 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6234 sp<FakeWindowHandle> window =
6235 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6236
6237 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6238 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
6239
6240 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6241 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6242 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6243 {100, 200}))
6244 << "The down event injected into the first display should succeed";
6245
6246 window->consumeMotionDown();
6247 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006248
6249 ASSERT_EQ(InputEventInjectionResult::FAILED,
6250 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6251 {100, 200}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006252 << "The down event injected into the second display should fail since there's no "
6253 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006254
6255 // Continue to inject event to first display.
6256 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6257 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6258 ADISPLAY_ID_DEFAULT, {110, 220}))
6259 << "The move event injected into the first display should succeed";
6260
6261 window->consumeMotionMove();
6262 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006263
6264 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6265 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6266 {110, 220}))
6267 << "The up event injected into the first display should succeed";
6268
6269 window->consumeMotionUp();
6270 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006271
6272 window->assertNoEvents();
6273 monitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00006274 secondMonitor.assertNoEvents();
6275}
6276
6277/**
6278 * Two displays
6279 * There is a monitor and foreground window on each display.
6280 * First, we inject down events into each of the two displays, at this point, the foreground windows
6281 * and monitors on both displays should receive down events.
6282 * At this point, the foreground window of the second display goes away, the gone window should
6283 * receive the cancel event, and the other windows and monitors should not receive any events.
6284 * Inject a move event into the second display. At this point, the injection should fail because
6285 * the second display no longer has a foreground window. At this point, the monitor on the second
6286 * display should receive a cancel event, and any windows or monitors on the first display should
6287 * not receive any events, and any subsequent injection of events into the second display should
6288 * also fail.
6289 * Continue to inject events into the first display, and the events should all be injected
6290 * successfully and received normally.
6291 */
6292TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCancelWhenAnotherDisplayMonitorTouchCanceled) {
6293 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6294 sp<FakeWindowHandle> window =
6295 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6296 sp<FakeWindowHandle> secondWindow =
6297 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondForeground",
6298 SECOND_DISPLAY_ID);
6299
6300 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6301 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
6302
6303 // There is a foreground window on both displays.
6304 mDispatcher->onWindowInfosChanged({{*window->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
6305 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6306 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6307 {100, 200}))
6308 << "The down event injected into the first display should succeed";
6309
6310 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6311 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006312
6313 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6314 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6315 {100, 200}))
6316 << "The down event injected into the second display should succeed";
6317
Linnan Lid8150952024-01-26 18:07:17 +00006318 secondWindow->consumeMotionDown(SECOND_DISPLAY_ID);
6319 secondMonitor.consumeMotionDown(SECOND_DISPLAY_ID);
6320
6321 // Now second window is gone away.
6322 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6323
6324 // The gone window should receive a cancel, and the monitor on the second display should not
6325 // receive any events.
Linnan Lid8150952024-01-26 18:07:17 +00006326 secondWindow->consumeMotionCancel(SECOND_DISPLAY_ID);
6327 secondMonitor.assertNoEvents();
6328
6329 ASSERT_EQ(InputEventInjectionResult::FAILED,
6330 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6331 SECOND_DISPLAY_ID, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006332 << "The move event injected into the second display should fail because there's no "
6333 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006334 // Now the monitor on the second display should receive a cancel event.
6335 secondMonitor.consumeMotionCancel(SECOND_DISPLAY_ID);
Linnan Lid8150952024-01-26 18:07:17 +00006336
6337 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6338 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6339 ADISPLAY_ID_DEFAULT, {110, 200}))
6340 << "The move event injected into the first display should succeed";
6341
6342 window->consumeMotionMove();
6343 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006344
6345 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006346 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6347 {110, 220}))
6348 << "The up event injected into the second display should fail because there's no "
6349 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006350
6351 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6352 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6353 {110, 220}))
6354 << "The up event injected into the first display should succeed";
6355
6356 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6357 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006358
Linnan Lid8150952024-01-26 18:07:17 +00006359 window->assertNoEvents();
6360 monitor.assertNoEvents();
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006361 secondWindow->assertNoEvents();
6362 secondMonitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00006363}
6364
6365/**
6366 * One display with transform
6367 * There is a foreground window and a monitor on the display
6368 * Inject down event and move event sequentially, the foreground window and monitor can receive down
6369 * event and move event, then let the foreground window go away, the foreground window receives
6370 * cancel event, inject move event again, the monitor receives cancel event, all the events received
6371 * by the monitor should be with the same transform as the display
6372 */
6373TEST_F(InputDispatcherMonitorTest, MonitorTouchCancelEventWithDisplayTransform) {
6374 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6375 sp<FakeWindowHandle> window =
6376 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6377 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6378
6379 ui::Transform transform;
6380 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6381
6382 gui::DisplayInfo displayInfo;
6383 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6384 displayInfo.transform = transform;
6385
6386 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
6387
6388 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6389 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6390 {100, 200}))
6391 << "The down event injected should succeed";
6392
6393 window->consumeMotionDown();
6394 std::unique_ptr<MotionEvent> downMotionEvent = monitor.consumeMotion();
6395 EXPECT_EQ(transform, downMotionEvent->getTransform());
6396 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, downMotionEvent->getAction());
6397
6398 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6399 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6400 ADISPLAY_ID_DEFAULT, {110, 220}))
6401 << "The move event injected should succeed";
6402
6403 window->consumeMotionMove();
6404 std::unique_ptr<MotionEvent> moveMotionEvent = monitor.consumeMotion();
6405 EXPECT_EQ(transform, moveMotionEvent->getTransform());
6406 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, moveMotionEvent->getAction());
6407
6408 // Let foreground window gone
6409 mDispatcher->onWindowInfosChanged({{}, {displayInfo}, 0, 0});
6410
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006411 // Foreground window should receive a cancel event, but not the monitor.
Linnan Lid8150952024-01-26 18:07:17 +00006412 window->consumeMotionCancel();
Linnan Lid8150952024-01-26 18:07:17 +00006413
6414 ASSERT_EQ(InputEventInjectionResult::FAILED,
6415 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6416 ADISPLAY_ID_DEFAULT, {110, 220}))
6417 << "The move event injected should failed";
6418 // Now foreground should not receive any events, but monitor should receive a cancel event
6419 // with transform that same as display's display.
Linnan Lid8150952024-01-26 18:07:17 +00006420 std::unique_ptr<MotionEvent> cancelMotionEvent = monitor.consumeMotion();
6421 EXPECT_EQ(transform, cancelMotionEvent->getTransform());
6422 EXPECT_EQ(ADISPLAY_ID_DEFAULT, cancelMotionEvent->getDisplayId());
6423 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, cancelMotionEvent->getAction());
6424
6425 // Other event inject to this display should fail.
6426 ASSERT_EQ(InputEventInjectionResult::FAILED,
6427 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6428 ADISPLAY_ID_DEFAULT, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006429 << "The up event injected should fail because the touched window was removed";
Linnan Lid8150952024-01-26 18:07:17 +00006430 window->assertNoEvents();
6431 monitor.assertNoEvents();
6432}
6433
chaviw81e2bb92019-12-18 15:03:51 -08006434TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006435 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006436 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6437 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08006438
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006439 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08006440
6441 NotifyMotionArgs motionArgs =
6442 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6443 ADISPLAY_ID_DEFAULT);
6444
Prabir Pradhan678438e2023-04-13 19:32:51 +00006445 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08006446 // Window should receive motion down event.
6447 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6448
6449 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08006450 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08006451 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6452 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
6453 motionArgs.pointerCoords[0].getX() - 10);
6454
Prabir Pradhan678438e2023-04-13 19:32:51 +00006455 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006456 window->consumeMotionMove(ADISPLAY_ID_DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08006457}
6458
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006459/**
6460 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
6461 * the device default right away. In the test scenario, we check both the default value,
6462 * and the action of enabling / disabling.
6463 */
6464TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07006465 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006466 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6467 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08006468 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006469
6470 // Set focused application.
6471 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006472 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006473
6474 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006475 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006476 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006477 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006478
6479 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006480 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006481 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006482 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006483
6484 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006485 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006486 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006487 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07006488 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006489 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006490 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006491 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006492
6493 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006494 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006495 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006496 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006497
6498 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006499 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006500 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006501 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07006502 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006503 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006504 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006505 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006506
6507 window->assertNoEvents();
6508}
6509
Gang Wange9087892020-01-07 12:17:14 -05006510TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006511 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006512 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6513 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05006514
6515 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006516 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05006517
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006518 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006519 setFocusedWindow(window);
6520
Harry Cutts33476232023-01-30 19:57:29 +00006521 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05006522
Prabir Pradhan678438e2023-04-13 19:32:51 +00006523 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
6524 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05006525
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006526 std::unique_ptr<KeyEvent> event = window->consumeKey();
6527 ASSERT_NE(event, nullptr);
6528 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Gang Wange9087892020-01-07 12:17:14 -05006529 ASSERT_NE(verified, nullptr);
6530 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
6531
6532 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
6533 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
6534 ASSERT_EQ(keyArgs.source, verified->source);
6535 ASSERT_EQ(keyArgs.displayId, verified->displayId);
6536
6537 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
6538
6539 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05006540 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006541 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05006542 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
6543 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
6544 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
6545 ASSERT_EQ(0, verifiedKey.repeatCount);
6546}
6547
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006548TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006549 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006550 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6551 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006552
6553 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6554
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006555 ui::Transform transform;
6556 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6557
6558 gui::DisplayInfo displayInfo;
6559 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6560 displayInfo.transform = transform;
6561
Patrick Williamsd828f302023-04-28 17:52:08 -05006562 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006563
Prabir Pradhan678438e2023-04-13 19:32:51 +00006564 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006565 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6566 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006567 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006568
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006569 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
6570 ASSERT_NE(nullptr, event);
6571 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006572 ASSERT_NE(verified, nullptr);
6573 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
6574
6575 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
6576 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
6577 EXPECT_EQ(motionArgs.source, verified->source);
6578 EXPECT_EQ(motionArgs.displayId, verified->displayId);
6579
6580 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
6581
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006582 const vec2 rawXY =
6583 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
6584 motionArgs.pointerCoords[0].getXYValue());
6585 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
6586 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006587 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006588 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006589 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006590 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
6591 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
6592}
6593
chaviw09c8d2d2020-08-24 15:48:26 -07006594/**
6595 * Ensure that separate calls to sign the same data are generating the same key.
6596 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
6597 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
6598 * tests.
6599 */
6600TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
6601 KeyEvent event = getTestKeyEvent();
6602 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6603
6604 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
6605 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
6606 ASSERT_EQ(hmac1, hmac2);
6607}
6608
6609/**
6610 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6611 */
6612TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6613 KeyEvent event = getTestKeyEvent();
6614 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6615 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6616
6617 verifiedEvent.deviceId += 1;
6618 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6619
6620 verifiedEvent.source += 1;
6621 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6622
6623 verifiedEvent.eventTimeNanos += 1;
6624 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6625
6626 verifiedEvent.displayId += 1;
6627 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6628
6629 verifiedEvent.action += 1;
6630 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6631
6632 verifiedEvent.downTimeNanos += 1;
6633 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6634
6635 verifiedEvent.flags += 1;
6636 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6637
6638 verifiedEvent.keyCode += 1;
6639 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6640
6641 verifiedEvent.scanCode += 1;
6642 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6643
6644 verifiedEvent.metaState += 1;
6645 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6646
6647 verifiedEvent.repeatCount += 1;
6648 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6649}
6650
Vishnu Nair958da932020-08-21 17:12:37 -07006651TEST_F(InputDispatcherTest, SetFocusedWindow) {
6652 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6653 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006654 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006655 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006656 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006657 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6658
6659 // Top window is also focusable but is not granted focus.
6660 windowTop->setFocusable(true);
6661 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006662 mDispatcher->onWindowInfosChanged(
6663 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006664 setFocusedWindow(windowSecond);
6665
6666 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006667 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006668 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006669
6670 // Focused window should receive event.
6671 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6672 windowTop->assertNoEvents();
6673}
6674
6675TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
6676 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6677 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006678 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006679 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6680
6681 window->setFocusable(true);
6682 // Release channel for window is no longer valid.
6683 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006684 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006685 setFocusedWindow(window);
6686
6687 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006688 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006689
6690 // window channel is invalid, so it should not receive any input event.
6691 window->assertNoEvents();
6692}
6693
6694TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
6695 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6696 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006697 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006698 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006699 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6700
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006701 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006702 setFocusedWindow(window);
6703
6704 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006705 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006706
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006707 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006708 window->assertNoEvents();
6709}
6710
6711TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6712 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6713 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006714 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006715 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006716 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006717 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6718
6719 windowTop->setFocusable(true);
6720 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006721 mDispatcher->onWindowInfosChanged(
6722 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006723 setFocusedWindow(windowTop);
6724 windowTop->consumeFocusEvent(true);
6725
Chavi Weingarten847e8512023-03-29 00:26:09 +00006726 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006727 mDispatcher->onWindowInfosChanged(
6728 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006729 windowSecond->consumeFocusEvent(true);
6730 windowTop->consumeFocusEvent(false);
6731
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006732 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006733 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006734
6735 // Focused window should receive event.
6736 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6737}
6738
Chavi Weingarten847e8512023-03-29 00:26:09 +00006739TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006740 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6741 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006742 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006743 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006744 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006745 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6746
6747 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006748 windowSecond->setFocusable(false);
6749 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006750 mDispatcher->onWindowInfosChanged(
6751 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006752 setFocusedWindow(windowTop);
6753 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006754
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006755 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006756 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006757
6758 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006759 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006760 windowSecond->assertNoEvents();
6761}
6762
6763TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6764 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6765 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006766 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006767 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006768 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6769 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006770 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6771
6772 window->setFocusable(true);
6773 previousFocusedWindow->setFocusable(true);
6774 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006775 mDispatcher->onWindowInfosChanged(
6776 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006777 setFocusedWindow(previousFocusedWindow);
6778 previousFocusedWindow->consumeFocusEvent(true);
6779
6780 // Requesting focus on invisible window takes focus from currently focused window.
6781 setFocusedWindow(window);
6782 previousFocusedWindow->consumeFocusEvent(false);
6783
6784 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006785 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006786 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6787 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006788
6789 // Window does not get focus event or key down.
6790 window->assertNoEvents();
6791
6792 // Window becomes visible.
6793 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006794 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006795
6796 // Window receives focus event.
6797 window->consumeFocusEvent(true);
6798 // Focused window receives key down.
6799 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6800}
6801
Vishnu Nair599f1412021-06-21 10:39:58 -07006802TEST_F(InputDispatcherTest, DisplayRemoved) {
6803 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6804 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006805 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006806 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6807
6808 // window is granted focus.
6809 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006810 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006811 setFocusedWindow(window);
6812 window->consumeFocusEvent(true);
6813
6814 // When a display is removed window loses focus.
6815 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6816 window->consumeFocusEvent(false);
6817}
6818
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006819/**
6820 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6821 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6822 * of the 'slipperyEnterWindow'.
6823 *
6824 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6825 * a way so that the touched location is no longer covered by the top window.
6826 *
6827 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6828 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6829 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6830 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6831 * with ACTION_DOWN).
6832 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6833 * window moved itself away from the touched location and had Flag::SLIPPERY.
6834 *
6835 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6836 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6837 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6838 *
6839 * In this test, we ensure that the event received by the bottom window has
6840 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6841 */
6842TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006843 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006844 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006845
6846 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6847 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6848
6849 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006850 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006851 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006852 // Make sure this one overlaps the bottom window
6853 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6854 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6855 // one. Windows with the same owner are not considered to be occluding each other.
6856 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6857
6858 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006859 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006860 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6861
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006862 mDispatcher->onWindowInfosChanged(
6863 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006864
6865 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006866 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6867 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6868 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006869 slipperyExitWindow->consumeMotionDown();
6870 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006871 mDispatcher->onWindowInfosChanged(
6872 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006873
Prabir Pradhan678438e2023-04-13 19:32:51 +00006874 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6875 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6876 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006877
6878 slipperyExitWindow->consumeMotionCancel();
6879
6880 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6881 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6882}
6883
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006884/**
6885 * Two windows, one on the left and another on the right. The left window is slippery. The right
6886 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6887 * touch moves from the left window into the right window, the gesture should continue to go to the
6888 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6889 * reproduces a crash.
6890 */
6891TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6892 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6893
6894 sp<FakeWindowHandle> leftSlipperyWindow =
6895 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6896 leftSlipperyWindow->setSlippery(true);
6897 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6898
6899 sp<FakeWindowHandle> rightDropTouchesWindow =
6900 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6901 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6902 rightDropTouchesWindow->setDropInput(true);
6903
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006904 mDispatcher->onWindowInfosChanged(
6905 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006906
6907 // Start touch in the left window
6908 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6909 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6910 .build());
6911 leftSlipperyWindow->consumeMotionDown();
6912
6913 // And move it into the right window
6914 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6915 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6916 .build());
6917
6918 // Since the right window isn't eligible to receive input, touch does not slip.
6919 // The left window continues to receive the gesture.
6920 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6921 rightDropTouchesWindow->assertNoEvents();
6922}
6923
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006924/**
6925 * A single window is on screen first. Touch is injected into that window. Next, a second window
6926 * appears. Since the first window is slippery, touch will move from the first window to the second.
6927 */
6928TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6929 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6930 sp<FakeWindowHandle> originalWindow =
6931 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6932 originalWindow->setFrame(Rect(0, 0, 200, 200));
6933 originalWindow->setSlippery(true);
6934
6935 sp<FakeWindowHandle> appearingWindow =
6936 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6937 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6938
6939 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6940
6941 // Touch down on the original window
6942 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6943 injectMotionEvent(*mDispatcher,
6944 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6945 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6946 .build()));
6947 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6948
6949 // Now, a new window appears. This could be, for example, a notification shade that appears
6950 // after user starts to drag down on the launcher window.
6951 mDispatcher->onWindowInfosChanged(
6952 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6953 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6954 injectMotionEvent(*mDispatcher,
6955 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6956 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6957 .build()));
6958 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6959 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6960 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6961 injectMotionEvent(*mDispatcher,
6962 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6963 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6964 .build()));
6965 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6966
6967 originalWindow->assertNoEvents();
6968 appearingWindow->assertNoEvents();
6969}
6970
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006971TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006972 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006973 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6974
6975 sp<FakeWindowHandle> leftWindow =
6976 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6977 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006978 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006979
6980 sp<FakeWindowHandle> rightSpy =
6981 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6982 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006983 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006984 rightSpy->setSpy(true);
6985 rightSpy->setTrustedOverlay(true);
6986
6987 sp<FakeWindowHandle> rightWindow =
6988 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6989 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006990 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006991
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006992 mDispatcher->onWindowInfosChanged(
6993 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006994
6995 // Touch in the left window
6996 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6997 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6998 .build());
6999 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
7000 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007001 ASSERT_NO_FATAL_FAILURE(
7002 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007003
7004 // Touch another finger over the right windows
7005 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7006 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7007 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7008 .build());
7009 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
7010 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
7011 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
7012 mDispatcher->waitForIdle();
7013 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007014 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
7015 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007016
7017 // Release finger over left window. The UP actions are not treated as device interaction.
7018 // The windows that did not receive the UP pointer will receive MOVE events, but since this
7019 // is part of the UP action, we do not treat this as device interaction.
7020 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
7021 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7022 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7023 .build());
7024 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
7025 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
7026 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
7027 mDispatcher->waitForIdle();
7028 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7029
7030 // Move remaining finger
7031 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7032 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7033 .build());
7034 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
7035 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
7036 mDispatcher->waitForIdle();
7037 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007038 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007039
7040 // Release all fingers
7041 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7042 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7043 .build());
7044 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
7045 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
7046 mDispatcher->waitForIdle();
7047 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7048}
7049
7050TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
7051 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7052
7053 sp<FakeWindowHandle> window =
7054 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
7055 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007056 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007057
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007058 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007059 setFocusedWindow(window);
7060 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
7061
7062 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
7063 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
7064 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007065 ASSERT_NO_FATAL_FAILURE(
7066 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007067
7068 // The UP actions are not treated as device interaction.
7069 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
7070 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
7071 mDispatcher->waitForIdle();
7072 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7073}
7074
Prabir Pradhan5893d362023-11-17 04:30:40 +00007075TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
7076 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7077
7078 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
7079 ADISPLAY_ID_DEFAULT);
7080 left->setFrame(Rect(0, 0, 100, 100));
7081 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
7082 "Right Window", ADISPLAY_ID_DEFAULT);
7083 right->setFrame(Rect(100, 0, 200, 100));
7084 sp<FakeWindowHandle> spy =
7085 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
7086 spy->setFrame(Rect(0, 0, 200, 100));
7087 spy->setTrustedOverlay(true);
7088 spy->setSpy(true);
7089
7090 mDispatcher->onWindowInfosChanged(
7091 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
7092
7093 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
7094 NotifyMotionArgs notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
7095 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
7096 mDispatcher->notifyMotion(notifyArgs);
7097
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007098 std::unique_ptr<MotionEvent> leftEnter = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00007099 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
7100 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007101 ASSERT_NE(nullptr, leftEnter);
Prabir Pradhan5893d362023-11-17 04:30:40 +00007102 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
7103 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007104 Not(WithEventId(leftEnter->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00007105 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
7106
7107 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
7108 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
7109 {PointF{150, 50}});
7110 mDispatcher->notifyMotion(notifyArgs);
7111
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007112 std::unique_ptr<MotionEvent> leftExit = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00007113 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
7114 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007115 ASSERT_NE(nullptr, leftExit);
Prabir Pradhan5893d362023-11-17 04:30:40 +00007116 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
7117 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007118 Not(WithEventId(leftExit->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00007119 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
7120
7121 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
7122}
7123
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00007124class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
7125protected:
7126 std::shared_ptr<FakeApplicationHandle> mApp;
7127 sp<FakeWindowHandle> mWindow;
7128
7129 virtual void SetUp() override {
7130 InputDispatcherTest::SetUp();
7131
7132 mApp = std::make_shared<FakeApplicationHandle>();
7133
7134 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
7135 mWindow->setFrame(Rect(0, 0, 100, 100));
7136
7137 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
7138 setFocusedWindow(mWindow);
7139 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
7140 }
7141
7142 void setFallback(int32_t keycode) {
7143 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
7144 return KeyEventBuilder(event).keyCode(keycode).build();
7145 });
7146 }
7147
7148 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007149 std::unique_ptr<KeyEvent> event = mWindow->consumeKey(handled);
7150 ASSERT_NE(nullptr, event);
7151 ASSERT_THAT(*event, matcher);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00007152 }
7153};
7154
7155TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
7156 mDispatcher->notifyKey(
7157 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7158 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
7159 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7160}
7161
7162TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
7163 mDispatcher->notifyKey(
7164 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7165 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
7166 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7167}
7168
7169TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
7170 mDispatcher->notifyKey(
7171 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7172
7173 // Do not handle this key event.
7174 consumeKey(/*handled=*/false,
7175 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7176 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7177
7178 // Since the policy did not request any fallback to be generated, ensure there are no events.
7179 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7180}
7181
7182TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
7183 setFallback(AKEYCODE_B);
7184 mDispatcher->notifyKey(
7185 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7186
7187 // Do not handle this key event.
7188 consumeKey(/*handled=*/false,
7189 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7190
7191 // Since the key was not handled, ensure the fallback event was dispatched instead.
7192 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7193 consumeKey(/*handled=*/true,
7194 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7195 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7196
7197 // Release the original key, and ensure the fallback key is also released.
7198 mDispatcher->notifyKey(
7199 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7200 consumeKey(/*handled=*/false,
7201 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7202 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7203 consumeKey(/*handled=*/true,
7204 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7205 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7206
7207 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7208 mWindow->assertNoEvents();
7209}
7210
7211TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
7212 setFallback(AKEYCODE_B);
7213 mDispatcher->notifyKey(
7214 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7215
7216 // Do not handle this key event, but handle the fallback.
7217 consumeKey(/*handled=*/false,
7218 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7219 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7220 consumeKey(/*handled=*/true,
7221 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7222 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7223
7224 // Release the original key, and ensure the fallback key is also released.
7225 mDispatcher->notifyKey(
7226 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7227 // But this time, the app handles the original key.
7228 consumeKey(/*handled=*/true,
7229 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7230 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7231 // Ensure the fallback key is canceled.
7232 consumeKey(/*handled=*/true,
7233 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7234 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7235
7236 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7237 mWindow->assertNoEvents();
7238}
7239
7240TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
7241 setFallback(AKEYCODE_B);
7242 mDispatcher->notifyKey(
7243 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7244
7245 // Do not handle this key event.
7246 consumeKey(/*handled=*/false,
7247 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7248 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7249 // App does not handle the fallback either, so ensure another fallback is not generated.
7250 setFallback(AKEYCODE_C);
7251 consumeKey(/*handled=*/false,
7252 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7253 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7254
7255 // Release the original key, and ensure the fallback key is also released.
7256 setFallback(AKEYCODE_B);
7257 mDispatcher->notifyKey(
7258 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7259 consumeKey(/*handled=*/false,
7260 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7261 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7262 consumeKey(/*handled=*/false,
7263 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7264 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7265
7266 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7267 mWindow->assertNoEvents();
7268}
7269
7270TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
7271 setFallback(AKEYCODE_B);
7272 mDispatcher->notifyKey(
7273 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7274
7275 // Do not handle this key event, so fallback is generated.
7276 consumeKey(/*handled=*/false,
7277 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7278 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7279 consumeKey(/*handled=*/true,
7280 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7281 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7282
7283 // Release the original key, but assume the policy is misbehaving and it
7284 // generates an inconsistent fallback to the one from the DOWN event.
7285 setFallback(AKEYCODE_C);
7286 mDispatcher->notifyKey(
7287 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7288 consumeKey(/*handled=*/false,
7289 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7290 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7291 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
7292 consumeKey(/*handled=*/true,
7293 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7294 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7295
7296 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7297 mWindow->assertNoEvents();
7298}
7299
7300TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
7301 setFallback(AKEYCODE_B);
7302 mDispatcher->notifyKey(
7303 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7304
7305 // Do not handle this key event, so fallback is generated.
7306 consumeKey(/*handled=*/false,
7307 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7308 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7309 consumeKey(/*handled=*/true,
7310 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7311 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7312
7313 // The original key is canceled.
7314 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
7315 .keyCode(AKEYCODE_A)
7316 .addFlag(AKEY_EVENT_FLAG_CANCELED)
7317 .build());
7318 consumeKey(/*handled=*/false,
7319 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
7320 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7321 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7322 // Ensure the fallback key is also canceled due to the original key being canceled.
7323 consumeKey(/*handled=*/true,
7324 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7325 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7326
7327 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7328 mWindow->assertNoEvents();
7329}
7330
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00007331TEST_F(InputDispatcherFallbackKeyTest, InputChannelRemovedDuringPolicyCall) {
Prabir Pradhanb13da8f2024-01-09 23:10:13 +00007332 setFallback(AKEYCODE_B);
7333 mDispatcher->notifyKey(
7334 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7335
7336 // Do not handle this key event.
7337 consumeKey(/*handled=*/false,
7338 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7339 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7340 consumeKey(/*handled=*/true,
7341 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7342 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7343
7344 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
7345 // When the unhandled key is reported to the policy next, remove the input channel.
7346 mDispatcher->removeInputChannel(mWindow->getToken());
7347 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
7348 });
7349 // Release the original key, and let the app now handle the previously unhandled key.
7350 // This should result in the previously generated fallback key to be cancelled.
7351 // Since the policy was notified of the unhandled DOWN event earlier, it will also be notified
7352 // of the UP event for consistency. The Dispatcher calls into the policy from its own thread
7353 // without holding the lock, because it need to synchronously fetch the fallback key. While in
7354 // the policy call, we will now remove the input channel. Once the policy call returns, the
7355 // Dispatcher will no longer have a channel to send cancellation events to. Ensure this does
7356 // not cause any crashes.
7357 mDispatcher->notifyKey(
7358 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7359 consumeKey(/*handled=*/true,
7360 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7361 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7362}
7363
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00007364TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedDuringPolicyCall) {
7365 setFallback(AKEYCODE_B);
7366 mDispatcher->notifyKey(
7367 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7368
7369 // Do not handle this key event.
7370 consumeKey(/*handled=*/false,
7371 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7372 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7373 consumeKey(/*handled=*/true,
7374 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7375 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7376
7377 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
7378 // When the unhandled key is reported to the policy next, remove the window.
7379 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
7380 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
7381 });
7382 // Release the original key, which the app will not handle. When this unhandled key is reported
7383 // to the policy, the window will be removed.
7384 mDispatcher->notifyKey(
7385 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7386 consumeKey(/*handled=*/false,
7387 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7388 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7389
7390 // Since the window was removed, it loses focus, and the channel state will be reset.
7391 consumeKey(/*handled=*/true,
7392 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7393 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7394 mWindow->consumeFocusEvent(false);
7395 mWindow->assertNoEvents();
7396}
7397
7398TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedWhileAwaitingFinishedSignal) {
7399 setFallback(AKEYCODE_B);
7400 mDispatcher->notifyKey(
7401 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7402
7403 // Do not handle this key event.
7404 consumeKey(/*handled=*/false,
7405 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7406 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7407 const auto [seq, event] = mWindow->receiveEvent();
7408 ASSERT_TRUE(seq.has_value() && event != nullptr) << "Failed to receive fallback event";
7409 ASSERT_EQ(event->getType(), InputEventType::KEY);
7410 ASSERT_THAT(static_cast<const KeyEvent&>(*event),
7411 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7412 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7413
7414 // Remove the window now, which should generate a cancellations and make the window lose focus.
7415 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
7416 consumeKey(/*handled=*/true,
7417 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
7418 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7419 consumeKey(/*handled=*/true,
7420 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7421 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7422 mWindow->consumeFocusEvent(false);
7423
7424 // Finish the event by reporting it as handled.
7425 mWindow->finishEvent(*seq);
7426 mWindow->assertNoEvents();
7427}
7428
Garfield Tan1c7bc862020-01-28 13:24:04 -08007429class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
7430protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08007431 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
7432 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007433
Chris Yea209fde2020-07-22 13:54:51 -07007434 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007435 sp<FakeWindowHandle> mWindow;
7436
7437 virtual void SetUp() override {
Prabir Pradhandae52792023-12-15 07:36:40 +00007438 InputDispatcherTest::SetUp();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007439
Prabir Pradhandae52792023-12-15 07:36:40 +00007440 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007441 setUpWindow();
7442 }
7443
7444 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07007445 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007446 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007447
Vishnu Nair47074b82020-08-14 11:54:47 -07007448 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007449 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007450 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007451 mWindow->consumeFocusEvent(true);
7452 }
7453
Chris Ye2ad95392020-09-01 13:44:44 -07007454 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007455 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007456 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007457 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007458 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007459
7460 // Window should receive key down event.
7461 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7462 }
7463
7464 void expectKeyRepeatOnce(int32_t repeatCount) {
7465 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007466 mWindow->consumeKeyEvent(
7467 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007468 }
7469
Chris Ye2ad95392020-09-01 13:44:44 -07007470 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007471 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007472 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007473 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007474 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007475
7476 // Window should receive key down event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007477 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007478 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007479 }
Hu Guofe3c8f12023-09-22 17:20:15 +08007480
7481 void injectKeyRepeat(int32_t repeatCount) {
7482 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7483 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, repeatCount, ADISPLAY_ID_DEFAULT))
7484 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
7485 }
Garfield Tan1c7bc862020-01-28 13:24:04 -08007486};
7487
7488TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00007489 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007490 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7491 expectKeyRepeatOnce(repeatCount);
7492 }
7493}
7494
7495TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00007496 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007497 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7498 expectKeyRepeatOnce(repeatCount);
7499 }
Harry Cutts33476232023-01-30 19:57:29 +00007500 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007501 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08007502 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7503 expectKeyRepeatOnce(repeatCount);
7504 }
7505}
7506
7507TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007508 sendAndConsumeKeyDown(/*deviceId=*/1);
7509 expectKeyRepeatOnce(/*repeatCount=*/1);
7510 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007511 mWindow->assertNoEvents();
7512}
7513
7514TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007515 sendAndConsumeKeyDown(/*deviceId=*/1);
7516 expectKeyRepeatOnce(/*repeatCount=*/1);
7517 sendAndConsumeKeyDown(/*deviceId=*/2);
7518 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007519 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00007520 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007521 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00007522 expectKeyRepeatOnce(/*repeatCount=*/2);
7523 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07007524 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00007525 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007526 mWindow->assertNoEvents();
7527}
7528
7529TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007530 sendAndConsumeKeyDown(/*deviceId=*/1);
7531 expectKeyRepeatOnce(/*repeatCount=*/1);
7532 sendAndConsumeKeyDown(/*deviceId=*/2);
7533 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007534 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00007535 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007536 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08007537 mWindow->assertNoEvents();
7538}
7539
liushenxiang42232912021-05-21 20:24:09 +08007540TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
7541 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00007542 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007543 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08007544 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
7545 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
7546 mWindow->assertNoEvents();
7547}
7548
Garfield Tan1c7bc862020-01-28 13:24:04 -08007549TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007550 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007551 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007552 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007553 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
7554 ASSERT_NE(nullptr, repeatEvent);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007555 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007556 IdGenerator::getSource(repeatEvent->getId()));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007557 }
7558}
7559
7560TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007561 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007562 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007563
7564 std::unordered_set<int32_t> idSet;
7565 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007566 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
7567 ASSERT_NE(nullptr, repeatEvent);
7568 int32_t id = repeatEvent->getId();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007569 EXPECT_EQ(idSet.end(), idSet.find(id));
7570 idSet.insert(id);
7571 }
7572}
7573
Hu Guofe3c8f12023-09-22 17:20:15 +08007574TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_CorrectRepeatCountWhenInjectKeyRepeat) {
7575 injectKeyRepeat(0);
7576 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7577 for (int32_t repeatCount = 1; repeatCount <= 2; ++repeatCount) {
7578 expectKeyRepeatOnce(repeatCount);
7579 }
7580 injectKeyRepeat(1);
7581 // Expect repeatCount to be 3 instead of 1
7582 expectKeyRepeatOnce(3);
7583}
7584
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007585/* Test InputDispatcher for MultiDisplay */
7586class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
7587public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007588 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007589 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08007590
Chris Yea209fde2020-07-22 13:54:51 -07007591 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007592 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007593 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007594
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007595 // Set focus window for primary display, but focused display would be second one.
7596 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07007597 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007598 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
7599
Vishnu Nair958da932020-08-21 17:12:37 -07007600 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007601 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08007602
Chris Yea209fde2020-07-22 13:54:51 -07007603 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007604 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007605 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007606 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007607 // Set focus display to second one.
7608 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
7609 // Set focus window for second display.
7610 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07007611 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007612 mDispatcher->onWindowInfosChanged(
7613 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007614 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007615 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007616 }
7617
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007618 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007619 InputDispatcherTest::TearDown();
7620
Chris Yea209fde2020-07-22 13:54:51 -07007621 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007622 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07007623 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007624 windowInSecondary.clear();
7625 }
7626
7627protected:
Chris Yea209fde2020-07-22 13:54:51 -07007628 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007629 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07007630 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007631 sp<FakeWindowHandle> windowInSecondary;
7632};
7633
7634TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
7635 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007636 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007637 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007638 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007639 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08007640 windowInSecondary->assertNoEvents();
7641
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007642 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007643 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007644 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007645 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007646 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007647 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08007648}
7649
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007650TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08007651 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007652 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007653 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007654 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007655 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08007656 windowInSecondary->assertNoEvents();
7657
7658 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007659 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007660 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007661 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007662 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08007663
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007664 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007665 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08007666
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007667 // Old focus should receive a cancel event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007668 windowInSecondary->consumeKeyUp(ADISPLAY_ID_NONE, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08007669
7670 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007671 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08007672 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007673 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08007674 windowInSecondary->assertNoEvents();
7675}
7676
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007677// Test per-display input monitors for motion event.
7678TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08007679 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007680 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007681 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007682 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007683
7684 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007685 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007686 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007687 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007688 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007689 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007690 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007691 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007692
7693 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007694 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007695 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007696 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007697 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007698 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007699 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08007700 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007701
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007702 // Lift up the touch from the second display
7703 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007704 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007705 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7706 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
7707 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
7708
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007709 // Test inject a non-pointer motion event.
7710 // If specific a display, it will dispatch to the focused window of particular display,
7711 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007712 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007713 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007714 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007715 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007716 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007717 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007718 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007719}
7720
7721// Test per-display input monitors for key event.
7722TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007723 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08007724 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007725 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007726 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007727 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007728
7729 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007730 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007731 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007732 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007733 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007734 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007735 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007736}
7737
Vishnu Nair958da932020-08-21 17:12:37 -07007738TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
7739 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007740 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007741 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007742 mDispatcher->onWindowInfosChanged(
7743 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
7744 *windowInSecondary->getInfo()},
7745 {},
7746 0,
7747 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007748 setFocusedWindow(secondWindowInPrimary);
7749 windowInPrimary->consumeFocusEvent(false);
7750 secondWindowInPrimary->consumeFocusEvent(true);
7751
7752 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007753 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7754 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007755 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007756 windowInPrimary->assertNoEvents();
7757 windowInSecondary->assertNoEvents();
7758 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7759}
7760
Arthur Hungdfd528e2021-12-08 13:23:04 +00007761TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
7762 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007763 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007764 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007765 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007766
7767 // Test touch down on primary display.
7768 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007769 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007770 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7771 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7772 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
7773
7774 // Test touch down on second display.
7775 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007776 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007777 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7778 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
7779 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
7780
7781 // Trigger cancel touch.
7782 mDispatcher->cancelCurrentTouch();
7783 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7784 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7785 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
7786 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
7787
7788 // Test inject a move motion event, no window/monitor should receive the event.
7789 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007790 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007791 ADISPLAY_ID_DEFAULT, {110, 200}))
7792 << "Inject motion event should return InputEventInjectionResult::FAILED";
7793 windowInPrimary->assertNoEvents();
7794 monitorInPrimary.assertNoEvents();
7795
7796 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007797 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007798 SECOND_DISPLAY_ID, {110, 200}))
7799 << "Inject motion event should return InputEventInjectionResult::FAILED";
7800 windowInSecondary->assertNoEvents();
7801 monitorInSecondary.assertNoEvents();
7802}
7803
Hu Guocb134f12023-12-23 13:42:44 +00007804/**
7805 * Send a key to the primary display and to the secondary display.
7806 * Then cause the key on the primary display to be canceled by sending in a stale key.
7807 * Ensure that the key on the primary display is canceled, and that the key on the secondary display
7808 * does not get canceled.
7809 */
7810TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture) {
7811 // Send a key down on primary display
7812 mDispatcher->notifyKey(
7813 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7814 .displayId(ADISPLAY_ID_DEFAULT)
7815 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7816 .build());
7817 windowInPrimary->consumeKeyEvent(
7818 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7819 windowInSecondary->assertNoEvents();
7820
7821 // Send a key down on second display
7822 mDispatcher->notifyKey(
7823 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7824 .displayId(SECOND_DISPLAY_ID)
7825 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7826 .build());
7827 windowInSecondary->consumeKeyEvent(
7828 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7829 windowInPrimary->assertNoEvents();
7830
7831 // Send a valid key up event on primary display that will be dropped because it is stale
7832 NotifyKeyArgs staleKeyUp =
7833 KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
7834 .displayId(ADISPLAY_ID_DEFAULT)
7835 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7836 .build();
7837 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7838 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7839 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7840 mDispatcher->notifyKey(staleKeyUp);
7841
7842 // Only the key gesture corresponding to the dropped event should receive the cancel event.
7843 // Therefore, windowInPrimary should get the cancel event and windowInSecondary should not
7844 // receive any events.
7845 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
7846 WithDisplayId(ADISPLAY_ID_DEFAULT),
7847 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7848 windowInSecondary->assertNoEvents();
7849}
7850
7851/**
7852 * Similar to 'WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture' but for motion events.
7853 */
7854TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropMotionEvent_OnlyCancelCorrespondingGesture) {
7855 // Send touch down on primary display.
7856 mDispatcher->notifyMotion(
7857 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7858 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7859 .displayId(ADISPLAY_ID_DEFAULT)
7860 .build());
7861 windowInPrimary->consumeMotionEvent(
7862 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7863 windowInSecondary->assertNoEvents();
7864
7865 // Send touch down on second display.
7866 mDispatcher->notifyMotion(
7867 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7868 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7869 .displayId(SECOND_DISPLAY_ID)
7870 .build());
7871 windowInPrimary->assertNoEvents();
7872 windowInSecondary->consumeMotionEvent(
7873 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7874
7875 // inject a valid MotionEvent on primary display that will be stale when it arrives.
7876 NotifyMotionArgs staleMotionUp =
7877 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7878 .displayId(ADISPLAY_ID_DEFAULT)
7879 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7880 .build();
7881 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7882 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7883 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7884 mDispatcher->notifyMotion(staleMotionUp);
7885
7886 // For stale motion events, we let the gesture to complete. This behaviour is different from key
7887 // events, where we would cancel the current keys instead.
7888 windowInPrimary->consumeMotionEvent(WithMotionAction(ACTION_UP));
7889 windowInSecondary->assertNoEvents();
7890}
7891
Jackal Guof9696682018-10-05 12:23:23 +08007892class InputFilterTest : public InputDispatcherTest {
7893protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007894 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
7895 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08007896 NotifyMotionArgs motionArgs;
7897
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007898 motionArgs =
7899 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007900 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007901 motionArgs =
7902 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007903 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007904 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007905 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007906 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007907 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08007908 } else {
7909 mFakePolicy->assertFilterInputEventWasNotCalled();
7910 }
7911 }
7912
7913 void testNotifyKey(bool expectToBeFiltered) {
7914 NotifyKeyArgs keyArgs;
7915
7916 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007917 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007918 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007919 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007920 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007921
7922 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08007923 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007924 } else {
7925 mFakePolicy->assertFilterInputEventWasNotCalled();
7926 }
7927 }
7928};
7929
7930// Test InputFilter for MotionEvent
7931TEST_F(InputFilterTest, MotionEvent_InputFilter) {
7932 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007933 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7934 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007935
7936 // Enable InputFilter
7937 mDispatcher->setInputFilterEnabled(true);
7938 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007939 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
7940 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007941
7942 // Disable InputFilter
7943 mDispatcher->setInputFilterEnabled(false);
7944 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007945 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7946 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007947}
7948
7949// Test InputFilter for KeyEvent
7950TEST_F(InputFilterTest, KeyEvent_InputFilter) {
7951 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007952 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007953
7954 // Enable InputFilter
7955 mDispatcher->setInputFilterEnabled(true);
7956 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007957 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007958
7959 // Disable InputFilter
7960 mDispatcher->setInputFilterEnabled(false);
7961 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007962 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007963}
7964
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007965// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
7966// logical display coordinate space.
7967TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
7968 ui::Transform firstDisplayTransform;
7969 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7970 ui::Transform secondDisplayTransform;
7971 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
7972
7973 std::vector<gui::DisplayInfo> displayInfos(2);
7974 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
7975 displayInfos[0].transform = firstDisplayTransform;
7976 displayInfos[1].displayId = SECOND_DISPLAY_ID;
7977 displayInfos[1].transform = secondDisplayTransform;
7978
Patrick Williamsd828f302023-04-28 17:52:08 -05007979 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007980
7981 // Enable InputFilter
7982 mDispatcher->setInputFilterEnabled(true);
7983
7984 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007985 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
7986 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007987}
7988
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007989class InputFilterInjectionPolicyTest : public InputDispatcherTest {
7990protected:
7991 virtual void SetUp() override {
7992 InputDispatcherTest::SetUp();
7993
7994 /**
7995 * We don't need to enable input filter to test the injected event policy, but we enabled it
7996 * here to make the tests more realistic, since this policy only matters when inputfilter is
7997 * on.
7998 */
7999 mDispatcher->setInputFilterEnabled(true);
8000
8001 std::shared_ptr<InputApplicationHandle> application =
8002 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008003 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
8004 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008005
8006 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8007 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008008 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008009 setFocusedWindow(mWindow);
8010 mWindow->consumeFocusEvent(true);
8011 }
8012
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008013 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
8014 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008015 KeyEvent event;
8016
8017 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
8018 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
8019 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00008020 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008021 const int32_t additionalPolicyFlags =
8022 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
8023 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00008024 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00008025 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008026 policyFlags | additionalPolicyFlags));
8027
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008028 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008029 }
8030
8031 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
8032 int32_t flags) {
8033 MotionEvent event;
8034 PointerProperties pointerProperties[1];
8035 PointerCoords pointerCoords[1];
8036 pointerProperties[0].clear();
8037 pointerProperties[0].id = 0;
8038 pointerCoords[0].clear();
8039 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
8040 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
8041
8042 ui::Transform identityTransform;
8043 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
8044 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
8045 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
8046 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
8047 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07008048 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07008049 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00008050 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008051
8052 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
8053 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00008054 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00008055 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008056 policyFlags | additionalPolicyFlags));
8057
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008058 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008059 }
8060
8061private:
8062 sp<FakeWindowHandle> mWindow;
8063};
8064
8065TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008066 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
8067 // filter. Without it, the event will no different from a regularly injected event, and the
8068 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00008069 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
8070 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008071}
8072
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008073TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008074 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00008075 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008076 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
8077}
8078
8079TEST_F(InputFilterInjectionPolicyTest,
8080 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
8081 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00008082 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008083 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008084}
8085
8086TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00008087 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
8088 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008089}
8090
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08008091class InputDispatcherUserActivityPokeTests : public InputDispatcherTest {
8092protected:
8093 virtual void SetUp() override {
8094 InputDispatcherTest::SetUp();
8095
8096 std::shared_ptr<FakeApplicationHandle> application =
8097 std::make_shared<FakeApplicationHandle>();
8098 application->setDispatchingTimeout(100ms);
8099 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
8100 ADISPLAY_ID_DEFAULT);
Yeabkal Wubshit222d83d2024-01-24 18:00:09 +00008101 mWindow->setFrame(Rect(0, 0, 100, 100));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08008102 mWindow->setDispatchingTimeout(100ms);
8103 mWindow->setFocusable(true);
8104
8105 // Set focused application.
8106 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8107
8108 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
8109 setFocusedWindow(mWindow);
8110 mWindow->consumeFocusEvent(true);
8111 }
8112
8113 void notifyAndConsumeMotion(int32_t action, uint32_t source, int32_t displayId,
8114 nsecs_t eventTime) {
8115 mDispatcher->notifyMotion(MotionArgsBuilder(action, source)
8116 .displayId(displayId)
8117 .eventTime(eventTime)
8118 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8119 .build());
8120 mWindow->consumeMotionEvent(WithMotionAction(action));
8121 }
8122
8123private:
8124 sp<FakeWindowHandle> mWindow;
8125};
8126
8127TEST_F_WITH_FLAGS(
8128 InputDispatcherUserActivityPokeTests, MinPokeTimeObserved,
8129 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8130 rate_limit_user_activity_poke_in_dispatcher))) {
8131 mDispatcher->setMinTimeBetweenUserActivityPokes(50ms);
8132
8133 // First event of type TOUCH. Should poke.
8134 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8135 milliseconds_to_nanoseconds(50));
8136 mFakePolicy->assertUserActivityPoked(
8137 {{milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8138
8139 // 80ns > 50ns has passed since previous TOUCH event. Should poke.
8140 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8141 milliseconds_to_nanoseconds(130));
8142 mFakePolicy->assertUserActivityPoked(
8143 {{milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8144
8145 // First event of type OTHER. Should poke (despite being within 50ns of previous TOUCH event).
8146 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8147 milliseconds_to_nanoseconds(135));
8148 mFakePolicy->assertUserActivityPoked(
8149 {{milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER, ADISPLAY_ID_DEFAULT}});
8150
8151 // Within 50ns of previous TOUCH event. Should NOT poke.
8152 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8153 milliseconds_to_nanoseconds(140));
8154 mFakePolicy->assertUserActivityNotPoked();
8155
8156 // Within 50ns of previous OTHER event. Should NOT poke.
8157 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8158 milliseconds_to_nanoseconds(150));
8159 mFakePolicy->assertUserActivityNotPoked();
8160
8161 // Within 50ns of previous TOUCH event (which was at time 130). Should NOT poke.
8162 // Note that STYLUS is mapped to TOUCH user activity, since it's a pointer-type source.
8163 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
8164 milliseconds_to_nanoseconds(160));
8165 mFakePolicy->assertUserActivityNotPoked();
8166
8167 // 65ns > 50ns has passed since previous OTHER event. Should poke.
8168 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8169 milliseconds_to_nanoseconds(200));
8170 mFakePolicy->assertUserActivityPoked(
8171 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER, ADISPLAY_ID_DEFAULT}});
8172
8173 // 170ns > 50ns has passed since previous TOUCH event. Should poke.
8174 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
8175 milliseconds_to_nanoseconds(300));
8176 mFakePolicy->assertUserActivityPoked(
8177 {{milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8178
8179 // Assert that there's no more user activity poke event.
8180 mFakePolicy->assertUserActivityNotPoked();
8181}
8182
8183TEST_F_WITH_FLAGS(
8184 InputDispatcherUserActivityPokeTests, DefaultMinPokeTimeOf100MsUsed,
8185 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8186 rate_limit_user_activity_poke_in_dispatcher))) {
8187 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8188 milliseconds_to_nanoseconds(200));
8189 mFakePolicy->assertUserActivityPoked(
8190 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8191
8192 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8193 milliseconds_to_nanoseconds(280));
8194 mFakePolicy->assertUserActivityNotPoked();
8195
8196 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8197 milliseconds_to_nanoseconds(340));
8198 mFakePolicy->assertUserActivityPoked(
8199 {{milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8200}
8201
8202TEST_F_WITH_FLAGS(
8203 InputDispatcherUserActivityPokeTests, ZeroMinPokeTimeDisablesRateLimiting,
8204 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8205 rate_limit_user_activity_poke_in_dispatcher))) {
8206 mDispatcher->setMinTimeBetweenUserActivityPokes(0ms);
8207
8208 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20);
8209 mFakePolicy->assertUserActivityPoked();
8210
8211 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 30);
8212 mFakePolicy->assertUserActivityPoked();
8213}
8214
chaviwfd6d3512019-03-25 13:23:49 -07008215class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008216 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07008217 InputDispatcherTest::SetUp();
8218
Chris Yea209fde2020-07-22 13:54:51 -07008219 std::shared_ptr<FakeApplicationHandle> application =
8220 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008221 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008222 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07008223 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07008224
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008225 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008226 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008227 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07008228
8229 // Set focused application.
8230 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07008231 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07008232
8233 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008234 mDispatcher->onWindowInfosChanged(
8235 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008236 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008237 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07008238 }
8239
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008240 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07008241 InputDispatcherTest::TearDown();
8242
8243 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008244 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07008245 }
8246
8247protected:
8248 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008249 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008250 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07008251};
8252
8253// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
8254// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
8255// the onPointerDownOutsideFocus callback.
8256TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008257 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008258 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008259 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008260 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008261 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008262
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008263 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07008264 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
8265}
8266
8267// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
8268// DOWN on the window that doesn't have focus. Ensure no window received the
8269// onPointerDownOutsideFocus callback.
8270TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008271 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008272 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
8273 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008274 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008275 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008276
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008277 ASSERT_TRUE(mDispatcher->waitForIdle());
8278 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008279}
8280
8281// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
8282// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
8283TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08008284 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008285 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008286 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008287 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07008288
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008289 ASSERT_TRUE(mDispatcher->waitForIdle());
8290 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008291}
8292
8293// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
8294// DOWN on the window that already has focus. Ensure no window received the
8295// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008296TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008297 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008298 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008299 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008300 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008301 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008302
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008303 ASSERT_TRUE(mDispatcher->waitForIdle());
8304 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008305}
8306
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008307// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
8308// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
8309TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
8310 const MotionEvent event =
8311 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
8312 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008313 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008314 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
8315 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008316 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008317 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8318 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
8319
8320 ASSERT_TRUE(mDispatcher->waitForIdle());
8321 mFakePolicy->assertOnPointerDownWasNotCalled();
8322 // Ensure that the unfocused window did not receive any FOCUS events.
8323 mUnfocusedWindow->assertNoEvents();
8324}
8325
chaviwaf87b3e2019-10-01 16:59:28 -07008326// These tests ensures we can send touch events to a single client when there are multiple input
8327// windows that point to the same client token.
8328class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
8329 virtual void SetUp() override {
8330 InputDispatcherTest::SetUp();
8331
Chris Yea209fde2020-07-22 13:54:51 -07008332 std::shared_ptr<FakeApplicationHandle> application =
8333 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008334 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
8335 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07008336 mWindow1->setFrame(Rect(0, 0, 100, 100));
8337
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00008338 mWindow2 = mWindow1->clone(ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07008339 mWindow2->setFrame(Rect(100, 100, 200, 200));
8340
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008341 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07008342 }
8343
8344protected:
8345 sp<FakeWindowHandle> mWindow1;
8346 sp<FakeWindowHandle> mWindow2;
8347
8348 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05008349 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07008350 vec2 vals = windowInfo->transform.transform(point.x, point.y);
8351 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07008352 }
8353
8354 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
8355 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008356 const std::string name = window->getName();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008357 std::unique_ptr<MotionEvent> motionEvent =
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008358 window->consumeMotionEvent(WithMotionAction(expectedAction));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008359 ASSERT_NE(nullptr, motionEvent);
8360 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07008361
8362 for (size_t i = 0; i < points.size(); i++) {
8363 float expectedX = points[i].x;
8364 float expectedY = points[i].y;
8365
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008366 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07008367 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008368 << ", got " << motionEvent->getX(i);
8369 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07008370 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008371 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07008372 }
8373 }
chaviw9eaa22c2020-07-01 16:21:27 -07008374
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008375 void touchAndAssertPositions(sp<FakeWindowHandle> touchedWindow, int32_t action,
8376 const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07008377 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008378 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
8379 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07008380
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008381 consumeMotionEvent(touchedWindow, action, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008382 }
chaviwaf87b3e2019-10-01 16:59:28 -07008383};
8384
8385TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
8386 // Touch Window 1
8387 PointF touchedPoint = {10, 10};
8388 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008389 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008390
8391 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008392 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008393
8394 // Touch Window 2
8395 touchedPoint = {150, 150};
8396 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008397 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008398}
8399
chaviw9eaa22c2020-07-01 16:21:27 -07008400TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
8401 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07008402 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008403 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07008404
8405 // Touch Window 1
8406 PointF touchedPoint = {10, 10};
8407 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008408 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008409 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008410 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008411
8412 // Touch Window 2
8413 touchedPoint = {150, 150};
8414 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008415 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
8416 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008417
chaviw9eaa22c2020-07-01 16:21:27 -07008418 // Update the transform so rotation is set
8419 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008420 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008421 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008422 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008423}
8424
chaviw9eaa22c2020-07-01 16:21:27 -07008425TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008426 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008427 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008428
8429 // Touch Window 1
8430 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8431 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008432 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008433
8434 // Touch Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008435 // Since this is part of the same touch gesture that has already been dispatched to Window 1,
8436 // the touch stream from Window 2 will be merged with the stream in Window 1. The merged stream
8437 // will continue to be dispatched through Window 1.
chaviw9eaa22c2020-07-01 16:21:27 -07008438 touchedPoints.push_back(PointF{150, 150});
8439 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008440 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008441
chaviw9eaa22c2020-07-01 16:21:27 -07008442 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008443 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008444 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008445
chaviw9eaa22c2020-07-01 16:21:27 -07008446 // Update the transform so rotation is set for Window 2
8447 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008448 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008449 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008450 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008451}
8452
chaviw9eaa22c2020-07-01 16:21:27 -07008453TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008454 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008455 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008456
8457 // Touch Window 1
8458 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8459 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008460 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008461
8462 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07008463 touchedPoints.push_back(PointF{150, 150});
8464 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008465
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008466 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008467
8468 // Move both windows
8469 touchedPoints = {{20, 20}, {175, 175}};
8470 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8471 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8472
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008473 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008474
chaviw9eaa22c2020-07-01 16:21:27 -07008475 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008476 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008477 expectedPoints.pop_back();
8478
8479 // Touch Window 2
8480 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008481 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008482 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008483 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008484
8485 // Move both windows
8486 touchedPoints = {{20, 20}, {175, 175}};
8487 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8488 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8489
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008490 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008491}
8492
8493TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
8494 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008495 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008496
8497 // Touch Window 1
8498 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8499 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008500 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008501
8502 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07008503 touchedPoints.push_back(PointF{150, 150});
8504 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008505
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008506 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008507
8508 // Move both windows
8509 touchedPoints = {{20, 20}, {175, 175}};
8510 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8511 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8512
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008513 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008514}
8515
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07008516/**
8517 * When one of the windows is slippery, the touch should not slip into the other window with the
8518 * same input channel.
8519 */
8520TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
8521 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008522 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07008523
8524 // Touch down in window 1
8525 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8526 ADISPLAY_ID_DEFAULT, {{50, 50}}));
8527 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
8528
8529 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
8530 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
8531 // getting generated.
8532 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8533 ADISPLAY_ID_DEFAULT, {{150, 150}}));
8534
8535 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
8536}
8537
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008538/**
8539 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
8540 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
8541 * that the pointer is hovering over may have a different transform.
8542 */
8543TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008544 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008545
8546 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008547 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
8548 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8549 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008550 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
8551 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008552 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008553 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8554 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
8555 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008556 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008557 consumeMotionEvent(mWindow2, ACTION_HOVER_ENTER,
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008558 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
8559}
8560
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008561class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
8562 virtual void SetUp() override {
8563 InputDispatcherTest::SetUp();
8564
Chris Yea209fde2020-07-22 13:54:51 -07008565 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008566 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008567 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
8568 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008569 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008570 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07008571 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008572
8573 // Set focused application.
8574 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8575
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008576 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008577 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008578 mWindow->consumeFocusEvent(true);
8579 }
8580
8581 virtual void TearDown() override {
8582 InputDispatcherTest::TearDown();
8583 mWindow.clear();
8584 }
8585
8586protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008587 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07008588 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008589 sp<FakeWindowHandle> mWindow;
8590 static constexpr PointF WINDOW_LOCATION = {20, 20};
8591
8592 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008593 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
8594 .x(WINDOW_LOCATION.x)
8595 .y(WINDOW_LOCATION.y);
8596 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8597 .pointer(touchingPointer)
8598 .build());
8599 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8600 .pointer(touchingPointer)
8601 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008602 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008603
8604 sp<FakeWindowHandle> addSpyWindow() {
8605 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008606 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008607 spy->setTrustedOverlay(true);
8608 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008609 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008610 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008611 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008612 return spy;
8613 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008614};
8615
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008616// Send a tap and respond, which should not cause an ANR.
8617TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
8618 tapOnWindow();
8619 mWindow->consumeMotionDown();
8620 mWindow->consumeMotionUp();
8621 ASSERT_TRUE(mDispatcher->waitForIdle());
8622 mFakePolicy->assertNotifyAnrWasNotCalled();
8623}
8624
8625// Send a regular key and respond, which should not cause an ANR.
8626TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008627 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008628 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8629 ASSERT_TRUE(mDispatcher->waitForIdle());
8630 mFakePolicy->assertNotifyAnrWasNotCalled();
8631}
8632
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008633TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
8634 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008635 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008636 mWindow->consumeFocusEvent(false);
8637
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008638 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008639 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8640 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00008641 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008643 // Key will not go to window because we have no focused window.
8644 // The 'no focused window' ANR timer should start instead.
8645
8646 // Now, the focused application goes away.
8647 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
8648 // The key should get dropped and there should be no ANR.
8649
8650 ASSERT_TRUE(mDispatcher->waitForIdle());
8651 mFakePolicy->assertNotifyAnrWasNotCalled();
8652}
8653
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008654// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008655// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8656// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008657TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008658 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008659 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008660 WINDOW_LOCATION));
8661
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008662 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008663 ASSERT_TRUE(sequenceNum);
8664 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008665 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008666
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008667 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008668 mWindow->consumeMotionEvent(
8669 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008670 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008671 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008672}
8673
8674// Send a key to the app and have the app not respond right away.
8675TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
8676 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008677 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008678 const auto [sequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008679 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008680 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008681 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008682 ASSERT_TRUE(mDispatcher->waitForIdle());
8683}
8684
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008685// We have a focused application, but no focused window
8686TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008687 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008688 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008689 mWindow->consumeFocusEvent(false);
8690
8691 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008692 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008693 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008694 WINDOW_LOCATION));
8695 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
8696 mDispatcher->waitForIdle();
8697 mFakePolicy->assertNotifyAnrWasNotCalled();
8698
8699 // Once a focused event arrives, we get an ANR for this application
8700 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8701 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008702 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008703 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008704 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008705 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008706 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07008707 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008708 ASSERT_TRUE(mDispatcher->waitForIdle());
8709}
8710
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008711/**
8712 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
8713 * there will not be an ANR.
8714 */
8715TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
8716 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008717 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008718 mWindow->consumeFocusEvent(false);
8719
8720 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07008721 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
8722 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008723 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
8724 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
8725
8726 // Define a valid key down event that is stale (too old).
8727 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00008728 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Hu Guofe3c8f12023-09-22 17:20:15 +08008729 AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008730
Hu Guofe3c8f12023-09-22 17:20:15 +08008731 const int32_t policyFlags =
8732 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008733
8734 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00008735 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008736 InputEventInjectionSync::WAIT_FOR_RESULT,
8737 INJECT_EVENT_TIMEOUT, policyFlags);
8738 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
8739 << "Injection should fail because the event is stale";
8740
8741 ASSERT_TRUE(mDispatcher->waitForIdle());
8742 mFakePolicy->assertNotifyAnrWasNotCalled();
8743 mWindow->assertNoEvents();
8744}
8745
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008746// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008747// Make sure that we don't notify policy twice about the same ANR.
8748TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008749 const std::chrono::duration appTimeout = 400ms;
8750 mApplication->setDispatchingTimeout(appTimeout);
8751 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8752
Vishnu Nair47074b82020-08-14 11:54:47 -07008753 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008754 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008755 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008756
8757 // Once a focused event arrives, we get an ANR for this application
8758 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8759 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008760 const std::chrono::duration eventInjectionTimeout = 100ms;
8761 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008762 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008763 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008764 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
8765 /*allowKeyRepeat=*/false);
8766 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
8767 << "result=" << ftl::enum_string(result);
8768 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
8769 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
8770 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
8771 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008772
Vishnu Naire4df8752022-09-08 09:17:55 -07008773 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008774 // ANR should not be raised again. It is up to policy to do that if it desires.
8775 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008776
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008777 // If we now get a focused window, the ANR should stop, but the policy handles that via
8778 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008779 ASSERT_TRUE(mDispatcher->waitForIdle());
8780}
8781
8782// We have a focused application, but no focused window
8783TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008784 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008785 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008786 mWindow->consumeFocusEvent(false);
8787
8788 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008789 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008790
Vishnu Naire4df8752022-09-08 09:17:55 -07008791 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8792 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008793
8794 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008795 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008796 ASSERT_TRUE(mDispatcher->waitForIdle());
8797 mWindow->assertNoEvents();
8798}
8799
8800/**
8801 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
8802 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
8803 * If we process 1 of the events, but ANR on the second event with the same timestamp,
8804 * the ANR mechanism should still work.
8805 *
8806 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
8807 * DOWN event, while not responding on the second one.
8808 */
8809TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
8810 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008811 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008812 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8813 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8814 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008815 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008816
8817 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008818 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008819 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8820 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8821 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008822 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008823
8824 // We have now sent down and up. Let's consume first event and then ANR on the second.
8825 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8826 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008827 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008828}
8829
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008830// A spy window can receive an ANR
8831TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
8832 sp<FakeWindowHandle> spy = addSpyWindow();
8833
8834 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008835 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008836 WINDOW_LOCATION));
8837 mWindow->consumeMotionDown();
8838
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008839 const auto [sequenceNum, _] = spy->receiveEvent(); // ACTION_DOWN
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008840 ASSERT_TRUE(sequenceNum);
8841 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008842 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008843
8844 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008845 spy->consumeMotionEvent(
8846 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008847 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008848 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008849}
8850
8851// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008852// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008853TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
8854 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008855
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008856 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008857 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008858 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008859 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008860
8861 // Stuck on the ACTION_UP
8862 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008863 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008864
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008865 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008866 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008867 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8868 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008869
8870 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8871 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008872 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008873 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008874 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008875}
8876
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008877// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008878// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008879TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
8880 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008881
8882 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008883 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8884 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008885
8886 mWindow->consumeMotionDown();
8887 // Stuck on the ACTION_UP
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
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008891 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008892 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008893 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8894 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008895
8896 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8897 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008898 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008899 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008900 spy->assertNoEvents();
8901}
8902
8903TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008904 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008905
Prabir Pradhanfb549072023-10-05 19:17:36 +00008906 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008907
8908 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008909 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008910 WINDOW_LOCATION));
8911
8912 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8913 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
8914 ASSERT_TRUE(consumeSeq);
8915
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008916 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
8917 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008918
8919 monitor.finishEvent(*consumeSeq);
8920 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
8921
8922 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008923 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008924}
8925
8926// If a window is unresponsive, then you get anr. if the window later catches up and starts to
8927// process events, you don't get an anr. When the window later becomes unresponsive again, you
8928// get an ANR again.
8929// 1. tap -> block on ACTION_UP -> receive ANR
8930// 2. consume all pending events (= queue becomes healthy again)
8931// 3. tap again -> block on ACTION_UP again -> receive ANR second time
8932TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
8933 tapOnWindow();
8934
8935 mWindow->consumeMotionDown();
8936 // Block on ACTION_UP
8937 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008938 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008939 mWindow->consumeMotionUp(); // Now the connection should be healthy again
8940 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008941 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008942 mWindow->assertNoEvents();
8943
8944 tapOnWindow();
8945 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008946 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008947 mWindow->consumeMotionUp();
8948
8949 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008950 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008951 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008952 mWindow->assertNoEvents();
8953}
8954
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008955// If a connection remains unresponsive for a while, make sure policy is only notified once about
8956// it.
8957TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008958 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008959 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008960 WINDOW_LOCATION));
8961
8962 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008963 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008964 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008965 // 'notifyConnectionUnresponsive' should only be called once per connection
8966 mFakePolicy->assertNotifyAnrWasNotCalled();
8967 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008968 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008969 mWindow->consumeMotionEvent(
8970 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008971 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008972 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008973 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008974 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008975}
8976
8977/**
8978 * 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 -07008979 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008980 */
8981TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008982 // The timeouts in this test are established by relying on the fact that the "key waiting for
8983 // events timeout" is equal to 500ms.
8984 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008985 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008986 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008987
8988 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008989 const auto& [downSequenceNum, downEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008990 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008991 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008992 ASSERT_TRUE(upSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008993
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008994 // Don't finish the events yet, and send a key
8995 mDispatcher->notifyKey(
8996 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
8997 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8998 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008999 // Key will not be sent to the window, yet, because the window is still processing events
9000 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009001 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009002 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009003
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009004 std::this_thread::sleep_for(400ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009005 // if we wait long enough though, dispatcher will give up, and still send the key
9006 // to the focused window, even though we have not yet finished the motion event
9007 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9008 mWindow->finishEvent(*downSequenceNum);
9009 mWindow->finishEvent(*upSequenceNum);
9010}
9011
9012/**
9013 * If a window is processing a motion event, and then a key event comes in, the key event should
9014 * not go to the focused window until the motion is processed.
9015 * If then a new motion comes in, then the pending key event should be going to the currently
9016 * focused window right away.
9017 */
9018TEST_F(InputDispatcherSingleWindowAnr,
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009019 PendingKey_IsDeliveredWhileMotionIsProcessingAndNewTouchComesIn) {
9020 // The timeouts in this test are established by relying on the fact that the "key waiting for
9021 // events timeout" is equal to 500ms.
9022 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009023 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009024 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009025
9026 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009027 const auto& [downSequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009028 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009029 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009030 ASSERT_TRUE(upSequenceNum);
9031 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08009032 mDispatcher->notifyKey(
9033 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
9034 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9035 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009036 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009037 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009038
9039 // Now tap down again. It should cause the pending key to go to the focused window right away.
9040 tapOnWindow();
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009041 // Now that we tapped, we should receive the key immediately.
9042 // Since there's still room for slowness, we use 200ms, which is much less than
9043 // the "key waiting for events' timeout of 500ms minus the already waited 100ms duration.
9044 std::unique_ptr<InputEvent> keyEvent = mWindow->consume(200ms);
9045 ASSERT_NE(nullptr, keyEvent);
9046 ASSERT_EQ(InputEventType::KEY, keyEvent->getType());
9047 ASSERT_THAT(static_cast<KeyEvent&>(*keyEvent), WithKeyAction(AKEY_EVENT_ACTION_DOWN));
9048 // it doesn't matter that we haven't ack'd the other events yet. We can finish events in any
9049 // order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009050 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
9051 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08009052 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9053 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009054 mWindow->assertNoEvents();
9055}
9056
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07009057/**
9058 * Send an event to the app and have the app not respond right away.
9059 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
9060 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
9061 * At some point, the window becomes responsive again.
9062 * Ensure that subsequent events get dropped, and the next gesture is delivered.
9063 */
9064TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
9065 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9066 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
9067 .build());
9068
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009069 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07009070 ASSERT_TRUE(sequenceNum);
9071 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9072 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
9073
9074 mWindow->finishEvent(*sequenceNum);
9075 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
9076 ASSERT_TRUE(mDispatcher->waitForIdle());
9077 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
9078
9079 // Now that the window is responsive, let's continue the gesture.
9080 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9081 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9082 .build());
9083
9084 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9085 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9086 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
9087 .build());
9088
9089 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9090 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9091 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
9092 .build());
9093 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9094 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9095 .build());
9096 // We already canceled this pointer, so the window shouldn't get any new events.
9097 mWindow->assertNoEvents();
9098
9099 // Start another one.
9100 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9101 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
9102 .build());
9103 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9104}
9105
Prabir Pradhanfc364722024-02-08 17:51:20 +00009106// Send an event to the app and have the app not respond right away. Then remove the app window.
9107// When the window is removed, the dispatcher will cancel the events for that window.
9108// So InputDispatcher will enqueue ACTION_CANCEL event as well.
9109TEST_F(InputDispatcherSingleWindowAnr, AnrAfterWindowRemoval) {
9110 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9111 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9112 {WINDOW_LOCATION}));
9113
9114 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
9115 ASSERT_TRUE(sequenceNum);
9116
9117 // Remove the window, but the input channel should remain alive.
9118 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
9119
9120 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9121 // Since the window was removed, Dispatcher does not know the PID associated with the window
9122 // anymore, so the policy is notified without the PID.
9123 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken(),
9124 /*pid=*/std::nullopt);
9125
9126 mWindow->finishEvent(*sequenceNum);
9127 // The cancellation was generated when the window was removed, along with the focus event.
9128 mWindow->consumeMotionEvent(
9129 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
9130 mWindow->consumeFocusEvent(false);
9131 ASSERT_TRUE(mDispatcher->waitForIdle());
9132 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
9133}
9134
9135// Send an event to the app and have the app not respond right away. Wait for the policy to be
9136// notified of the unresponsive window, then remove the app window.
9137TEST_F(InputDispatcherSingleWindowAnr, AnrFollowedByWindowRemoval) {
9138 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9139 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9140 {WINDOW_LOCATION}));
9141
9142 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
9143 ASSERT_TRUE(sequenceNum);
9144 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9145 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
9146
9147 // Remove the window, but the input channel should remain alive.
9148 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
9149
9150 mWindow->finishEvent(*sequenceNum);
9151 // The cancellation was generated during the ANR, and the window lost focus when it was removed.
9152 mWindow->consumeMotionEvent(
9153 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
9154 mWindow->consumeFocusEvent(false);
9155 ASSERT_TRUE(mDispatcher->waitForIdle());
9156 // Since the window was removed, Dispatcher does not know the PID associated with the window
9157 // becoming responsive, so the policy is notified without the PID.
9158 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
9159}
9160
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009161class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
9162 virtual void SetUp() override {
9163 InputDispatcherTest::SetUp();
9164
Chris Yea209fde2020-07-22 13:54:51 -07009165 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009166 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009167 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
9168 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009169 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009170 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009171 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009172
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009173 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
9174 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009175 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009176 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009177
9178 // Set focused application.
9179 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07009180 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009181
9182 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009183 mDispatcher->onWindowInfosChanged(
9184 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009185 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009186 mFocusedWindow->consumeFocusEvent(true);
9187 }
9188
9189 virtual void TearDown() override {
9190 InputDispatcherTest::TearDown();
9191
9192 mUnfocusedWindow.clear();
9193 mFocusedWindow.clear();
9194 }
9195
9196protected:
Chris Yea209fde2020-07-22 13:54:51 -07009197 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009198 sp<FakeWindowHandle> mUnfocusedWindow;
9199 sp<FakeWindowHandle> mFocusedWindow;
9200 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
9201 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
9202 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
9203
9204 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
9205
9206 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
9207
9208private:
9209 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009210 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009211 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009212 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009213 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009214 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009215 location));
9216 }
9217};
9218
9219// If we have 2 windows that are both unresponsive, the one with the shortest timeout
9220// should be ANR'd first.
9221TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009222 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009223 injectMotionEvent(*mDispatcher,
9224 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9225 AINPUT_SOURCE_TOUCHSCREEN)
9226 .pointer(PointerBuilder(0, ToolType::FINGER)
9227 .x(FOCUSED_WINDOW_LOCATION.x)
9228 .y(FOCUSED_WINDOW_LOCATION.y))
9229 .build()));
9230 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9231 injectMotionEvent(*mDispatcher,
9232 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
9233 AINPUT_SOURCE_TOUCHSCREEN)
9234 .pointer(PointerBuilder(0, ToolType::FINGER)
9235 .x(FOCUSED_WINDOW_LOCATION.x)
9236 .y(FOCUSED_WINDOW_LOCATION.y))
9237 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009238 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009239 mFocusedWindow->consumeMotionUp();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009240 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009241 // We consumed all events, so no ANR
9242 ASSERT_TRUE(mDispatcher->waitForIdle());
9243 mFakePolicy->assertNotifyAnrWasNotCalled();
9244
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009245 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009246 injectMotionEvent(*mDispatcher,
9247 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9248 AINPUT_SOURCE_TOUCHSCREEN)
9249 .pointer(PointerBuilder(0, ToolType::FINGER)
9250 .x(FOCUSED_WINDOW_LOCATION.x)
9251 .y(FOCUSED_WINDOW_LOCATION.y))
9252 .build()));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009253 const auto [unfocusedSequenceNum, _] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009254 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009255
9256 const std::chrono::duration timeout =
9257 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009258 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009259
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009260 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009261 mFocusedWindow->consumeMotionDown();
9262 // This cancel is generated because the connection was unresponsive
9263 mFocusedWindow->consumeMotionCancel();
9264 mFocusedWindow->assertNoEvents();
9265 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009266 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009267 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9268 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009269 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009270}
9271
9272// If we have 2 windows with identical timeouts that are both unresponsive,
9273// it doesn't matter which order they should have ANR.
9274// But we should receive ANR for both.
9275TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
9276 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009277 mUnfocusedWindow->setDispatchingTimeout(
9278 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009279 mDispatcher->onWindowInfosChanged(
9280 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009281
9282 tapOnFocusedWindow();
9283 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009284 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009285 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
9286 mFocusedWindow->getDispatchingTimeout(
9287 DISPATCHING_TIMEOUT)),
9288 mFakePolicy->getUnresponsiveWindowToken(0ms)};
9289
9290 ASSERT_THAT(anrConnectionTokens,
9291 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
9292 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009293
9294 ASSERT_TRUE(mDispatcher->waitForIdle());
9295 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009296
9297 mFocusedWindow->consumeMotionDown();
9298 mFocusedWindow->consumeMotionUp();
9299 mUnfocusedWindow->consumeMotionOutside();
9300
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009301 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
9302 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009303
9304 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009305 ASSERT_THAT(responsiveTokens,
9306 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
9307 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009308 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009309}
9310
9311// If a window is already not responding, the second tap on the same window should be ignored.
9312// We should also log an error to account for the dropped event (not tested here).
9313// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
9314TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
9315 tapOnFocusedWindow();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009316 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009317 // Receive the events, but don't respond
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009318 const auto [downEventSequenceNum, downEvent] = mFocusedWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009319 ASSERT_TRUE(downEventSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009320 const auto [upEventSequenceNum, upEvent] = mFocusedWindow->receiveEvent(); // ACTION_UP
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009321 ASSERT_TRUE(upEventSequenceNum);
9322 const std::chrono::duration timeout =
9323 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009324 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009325
9326 // Tap once again
9327 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009328 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009329 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009330 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009331 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009332 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009333 FOCUSED_WINDOW_LOCATION));
9334 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
9335 // valid touch target
9336 mUnfocusedWindow->assertNoEvents();
9337
9338 // Consume the first tap
9339 mFocusedWindow->finishEvent(*downEventSequenceNum);
9340 mFocusedWindow->finishEvent(*upEventSequenceNum);
9341 ASSERT_TRUE(mDispatcher->waitForIdle());
9342 // The second tap did not go to the focused window
9343 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009344 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08009345 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9346 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009347 mFakePolicy->assertNotifyAnrWasNotCalled();
9348}
9349
9350// If you tap outside of all windows, there will not be ANR
9351TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009352 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009353 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009354 LOCATION_OUTSIDE_ALL_WINDOWS));
9355 ASSERT_TRUE(mDispatcher->waitForIdle());
9356 mFakePolicy->assertNotifyAnrWasNotCalled();
9357}
9358
9359// Since the focused window is paused, tapping on it should not produce any events
9360TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
9361 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009362 mDispatcher->onWindowInfosChanged(
9363 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009364
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009365 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009366 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009367 FOCUSED_WINDOW_LOCATION));
9368
9369 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
9370 ASSERT_TRUE(mDispatcher->waitForIdle());
9371 // Should not ANR because the window is paused, and touches shouldn't go to it
9372 mFakePolicy->assertNotifyAnrWasNotCalled();
9373
9374 mFocusedWindow->assertNoEvents();
9375 mUnfocusedWindow->assertNoEvents();
9376}
9377
9378/**
9379 * 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 -07009380 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009381 * If a different window becomes focused at this time, the key should go to that window instead.
9382 *
9383 * Warning!!!
9384 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
9385 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009386 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009387 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
9388 *
9389 * If that value changes, this test should also change.
9390 */
9391TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
9392 // Set a long ANR timeout to prevent it from triggering
9393 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009394 mDispatcher->onWindowInfosChanged(
9395 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009396
9397 tapOnUnfocusedWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009398 const auto [downSequenceNum, downEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009399 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009400 const auto [upSequenceNum, upEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009401 ASSERT_TRUE(upSequenceNum);
9402 // Don't finish the events yet, and send a key
9403 // Injection will succeed because we will eventually give up and send the key to the focused
9404 // window even if motions are still being processed.
9405
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009406 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009407 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9408 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009409 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009410 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009411 // and the key remains pending, waiting for the touch events to be processed.
9412 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
9413 // under the hood.
9414 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
9415 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009416
9417 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07009418 mFocusedWindow->setFocusable(false);
9419 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009420 mDispatcher->onWindowInfosChanged(
9421 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009422 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009423
9424 // Focus events should precede the key events
9425 mUnfocusedWindow->consumeFocusEvent(true);
9426 mFocusedWindow->consumeFocusEvent(false);
9427
9428 // Finish the tap events, which should unblock dispatcher
9429 mUnfocusedWindow->finishEvent(*downSequenceNum);
9430 mUnfocusedWindow->finishEvent(*upSequenceNum);
9431
9432 // Now that all queues are cleared and no backlog in the connections, the key event
9433 // can finally go to the newly focused "mUnfocusedWindow".
9434 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9435 mFocusedWindow->assertNoEvents();
9436 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009437 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009438}
9439
9440// When the touch stream is split across 2 windows, and one of them does not respond,
9441// then ANR should be raised and the touch should be canceled for the unresponsive window.
9442// The other window should not be affected by that.
9443TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
9444 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00009445 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9446 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9447 {FOCUSED_WINDOW_LOCATION}));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009448 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009449
9450 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00009451 mDispatcher->notifyMotion(
9452 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9453 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009454
9455 const std::chrono::duration timeout =
9456 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009457 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009458
9459 mUnfocusedWindow->consumeMotionDown();
9460 mFocusedWindow->consumeMotionDown();
9461 // Focused window may or may not receive ACTION_MOVE
9462 // But it should definitely receive ACTION_CANCEL due to the ANR
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009463 const auto [moveOrCancelSequenceNum, event] = mFocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009464 ASSERT_TRUE(moveOrCancelSequenceNum);
9465 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
9466 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009467 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009468 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
9469 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
9470 mFocusedWindow->consumeMotionCancel();
9471 } else {
9472 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
9473 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009474 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009475 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9476 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009477
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009478 mUnfocusedWindow->assertNoEvents();
9479 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009480 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009481}
9482
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009483/**
9484 * If we have no focused window, and a key comes in, we start the ANR timer.
9485 * The focused application should add a focused window before the timer runs out to prevent ANR.
9486 *
9487 * If the user touches another application during this time, the key should be dropped.
9488 * Next, if a new focused window comes in, without toggling the focused application,
9489 * then no ANR should occur.
9490 *
9491 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
9492 * but in some cases the policy may not update the focused application.
9493 */
9494TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
9495 std::shared_ptr<FakeApplicationHandle> focusedApplication =
9496 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07009497 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009498 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
9499 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
9500 mFocusedWindow->setFocusable(false);
9501
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009502 mDispatcher->onWindowInfosChanged(
9503 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009504 mFocusedWindow->consumeFocusEvent(false);
9505
9506 // Send a key. The ANR timer should start because there is no focused window.
9507 // 'focusedApplication' will get blamed if this timer completes.
9508 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009509 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009510 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9511 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00009512 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009513 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009514
9515 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
9516 // then the injected touches won't cause the focused event to get dropped.
9517 // The dispatcher only checks for whether the queue should be pruned upon queueing.
9518 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
9519 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
9520 // For this test, it means that the key would get delivered to the window once it becomes
9521 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009522 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009523
9524 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00009525 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9526 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9527 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009528
9529 // We do not consume the motion right away, because that would require dispatcher to first
9530 // process (== drop) the key event, and by that time, ANR will be raised.
9531 // Set the focused window first.
9532 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009533 mDispatcher->onWindowInfosChanged(
9534 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009535 setFocusedWindow(mFocusedWindow);
9536 mFocusedWindow->consumeFocusEvent(true);
9537 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
9538 // to another application. This could be a bug / behaviour in the policy.
9539
9540 mUnfocusedWindow->consumeMotionDown();
9541
9542 ASSERT_TRUE(mDispatcher->waitForIdle());
9543 // Should not ANR because we actually have a focused window. It was just added too slowly.
9544 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
9545}
9546
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -08009547/**
9548 * If we are pruning input queue, we should never drop pointer events. Otherwise, we risk having
9549 * an inconsistent event stream inside the dispatcher. In this test, we make sure that the
9550 * dispatcher doesn't prune pointer events incorrectly.
9551 *
9552 * This test reproduces a crash in InputDispatcher.
9553 * To reproduce the crash, we need to simulate the conditions for "pruning input queue" to occur.
9554 *
9555 * Keep the currently focused application (mApplication), and have no focused window.
9556 * We set up two additional windows:
9557 * 1) The navigation bar window. This simulates the system "NavigationBar", which is used in the
9558 * 3-button navigation mode. This window injects a BACK button when it's touched. 2) The application
9559 * window. This window is not focusable, but is touchable.
9560 *
9561 * We first touch the navigation bar, which causes it to inject a key. Since there's no focused
9562 * window, the dispatcher doesn't process this key, and all other events inside dispatcher are now
9563 * blocked. The dispatcher is waiting for 'mApplication' to add a focused window.
9564 *
9565 * Now, we touch "Another window". This window is owned by a different application than
9566 * 'mApplication'. This causes the dispatcher to stop waiting for 'mApplication' to add a focused
9567 * window. Now, the "pruning input queue" behaviour should kick in, and the dispatcher should start
9568 * dropping the events from its queue. Ensure that no crash occurs.
9569 *
9570 * In this test, we are setting long timeouts to prevent ANRs and events dropped due to being stale.
9571 * This does not affect the test running time.
9572 */
9573TEST_F(InputDispatcherMultiWindowAnr, PruningInputQueueShouldNotDropPointerEvents) {
9574 std::shared_ptr<FakeApplicationHandle> systemUiApplication =
9575 std::make_shared<FakeApplicationHandle>();
9576 systemUiApplication->setDispatchingTimeout(3000ms);
9577 mFakePolicy->setStaleEventTimeout(3000ms);
9578 sp<FakeWindowHandle> navigationBar =
9579 sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
9580 ADISPLAY_ID_DEFAULT);
9581 navigationBar->setFocusable(false);
9582 navigationBar->setWatchOutsideTouch(true);
9583 navigationBar->setFrame(Rect(0, 0, 100, 100));
9584
9585 mApplication->setDispatchingTimeout(3000ms);
9586 // 'mApplication' is already focused, but we call it again here to make it explicit.
9587 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
9588
9589 std::shared_ptr<FakeApplicationHandle> anotherApplication =
9590 std::make_shared<FakeApplicationHandle>();
9591 sp<FakeWindowHandle> appWindow =
9592 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
9593 ADISPLAY_ID_DEFAULT);
9594 appWindow->setFocusable(false);
9595 appWindow->setFrame(Rect(100, 100, 200, 200));
9596
9597 mDispatcher->onWindowInfosChanged(
9598 {{*navigationBar->getInfo(), *appWindow->getInfo()}, {}, 0, 0});
9599 // 'mFocusedWindow' is no longer in the dispatcher window list, and therefore loses focus
9600 mFocusedWindow->consumeFocusEvent(false);
9601
9602 // Touch down the navigation bar. It consumes the touch and injects a key into the dispatcher
9603 // in response.
9604 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9605 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9606 .build());
9607 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9608
9609 // Key will not be sent anywhere because we have no focused window. It will remain pending.
9610 // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
9611 InputEventInjectionResult result =
9612 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9613 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
9614 /*allowKeyRepeat=*/false);
9615 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
9616
9617 // Finish the gesture - lift up finger and inject ACTION_UP key event
9618 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9619 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9620 .build());
9621 result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9622 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
9623 /*allowKeyRepeat=*/false);
9624 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
9625 // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
9626 // getting any events yet.
9627 navigationBar->assertNoEvents();
9628
9629 // Now touch "Another window". This touch is going to a different application than the one we
9630 // are waiting for (which is 'mApplication').
9631 // This should cause the dispatcher to drop the pending focus-dispatched events (like the key
9632 // trying to be injected) and to continue processing the rest of the events in the original
9633 // order.
9634 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9635 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
9636 .build());
9637 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_UP));
9638 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
9639 appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9640
9641 appWindow->assertNoEvents();
9642 navigationBar->assertNoEvents();
9643}
9644
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009645// These tests ensure we cannot send touch events to a window that's positioned behind a window
9646// that has feature NO_INPUT_CHANNEL.
9647// Layout:
9648// Top (closest to user)
9649// mNoInputWindow (above all windows)
9650// mBottomWindow
9651// Bottom (furthest from user)
9652class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
9653 virtual void SetUp() override {
9654 InputDispatcherTest::SetUp();
9655
9656 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009657 mNoInputWindow =
9658 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
9659 "Window without input channel", ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009660 /*createInputChannel=*/false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009661 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009662 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
9663 // It's perfectly valid for this window to not have an associated input channel
9664
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009665 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
9666 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009667 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
9668
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009669 mDispatcher->onWindowInfosChanged(
9670 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009671 }
9672
9673protected:
9674 std::shared_ptr<FakeApplicationHandle> mApplication;
9675 sp<FakeWindowHandle> mNoInputWindow;
9676 sp<FakeWindowHandle> mBottomWindow;
9677};
9678
9679TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
9680 PointF touchedPoint = {10, 10};
9681
Prabir Pradhan678438e2023-04-13 19:32:51 +00009682 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9683 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9684 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009685
9686 mNoInputWindow->assertNoEvents();
9687 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
9688 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
9689 // and therefore should prevent mBottomWindow from receiving touches
9690 mBottomWindow->assertNoEvents();
9691}
9692
9693/**
9694 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
9695 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
9696 */
9697TEST_F(InputDispatcherMultiWindowOcclusionTests,
9698 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009699 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
9700 "Window with input channel and NO_INPUT_CHANNEL",
9701 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009702
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009703 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009704 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009705 mDispatcher->onWindowInfosChanged(
9706 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009707
9708 PointF touchedPoint = {10, 10};
9709
Prabir Pradhan678438e2023-04-13 19:32:51 +00009710 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9711 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9712 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009713
9714 mNoInputWindow->assertNoEvents();
9715 mBottomWindow->assertNoEvents();
9716}
9717
Vishnu Nair958da932020-08-21 17:12:37 -07009718class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
9719protected:
9720 std::shared_ptr<FakeApplicationHandle> mApp;
9721 sp<FakeWindowHandle> mWindow;
9722 sp<FakeWindowHandle> mMirror;
9723
9724 virtual void SetUp() override {
9725 InputDispatcherTest::SetUp();
9726 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009727 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009728 mMirror = mWindow->clone(ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07009729 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
9730 mWindow->setFocusable(true);
9731 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009732 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009733 }
9734};
9735
9736TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
9737 // Request focus on a mirrored window
9738 setFocusedWindow(mMirror);
9739
9740 // window gets focused
9741 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009742 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009743 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009744 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
9745}
9746
9747// A focused & mirrored window remains focused only if the window and its mirror are both
9748// focusable.
9749TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
9750 setFocusedWindow(mMirror);
9751
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009752 // window gets focused because it is above the mirror
Vishnu Nair958da932020-08-21 17:12:37 -07009753 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009754 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009755 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009756 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009757 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009758 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009759 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9760
9761 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009762 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009763
9764 // window loses focus since one of the windows associated with the token in not focusable
9765 mWindow->consumeFocusEvent(false);
9766
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009767 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009768 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009769 mWindow->assertNoEvents();
9770}
9771
9772// A focused & mirrored window remains focused until the window and its mirror both become
9773// invisible.
9774TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
9775 setFocusedWindow(mMirror);
9776
9777 // window gets focused
9778 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009779 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009780 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009781 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009782 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009783 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009784 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9785
9786 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009787 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009788
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009789 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009790 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009791 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009792 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009793 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009794 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9795
9796 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009797 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009798
9799 // window loses focus only after all windows associated with the token become invisible.
9800 mWindow->consumeFocusEvent(false);
9801
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009802 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009803 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009804 mWindow->assertNoEvents();
9805}
9806
9807// A focused & mirrored window remains focused until both windows are removed.
9808TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
9809 setFocusedWindow(mMirror);
9810
9811 // window gets focused
9812 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009813 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009814 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009815 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009816 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*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->consumeKeyUp(ADISPLAY_ID_NONE);
9819
9820 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009821 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009822
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009823 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009824 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009825 mMirror->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009826 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009827 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009828 mMirror->consumeKeyUp(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07009829
9830 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009831 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009832 mWindow->consumeFocusEvent(false);
9833
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009834 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009835 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009836 mWindow->assertNoEvents();
9837}
9838
9839// Focus request can be pending until one window becomes visible.
9840TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
9841 // Request focus on an invisible mirror.
9842 mWindow->setVisible(false);
9843 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009844 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009845 setFocusedWindow(mMirror);
9846
9847 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009848 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009849 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9850 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07009851
9852 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009853 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009854
9855 // window gets focused
9856 mWindow->consumeFocusEvent(true);
9857 // window gets the pending key event
9858 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9859}
Prabir Pradhan99987712020-11-10 18:43:05 -08009860
9861class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
9862protected:
9863 std::shared_ptr<FakeApplicationHandle> mApp;
9864 sp<FakeWindowHandle> mWindow;
9865 sp<FakeWindowHandle> mSecondWindow;
9866
9867 void SetUp() override {
9868 InputDispatcherTest::SetUp();
9869 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009870 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009871 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009872 mSecondWindow =
9873 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009874 mSecondWindow->setFocusable(true);
9875
9876 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009877 mDispatcher->onWindowInfosChanged(
9878 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08009879
9880 setFocusedWindow(mWindow);
9881 mWindow->consumeFocusEvent(true);
9882 }
9883
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009884 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009885 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08009886 }
9887
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009888 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
9889 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08009890 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009891 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
9892 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009893 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009894 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08009895 }
9896};
9897
9898TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
9899 // Ensure that capture cannot be obtained for unfocused windows.
9900 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
9901 mFakePolicy->assertSetPointerCaptureNotCalled();
9902 mSecondWindow->assertNoEvents();
9903
9904 // Ensure that capture can be enabled from the focus window.
9905 requestAndVerifyPointerCapture(mWindow, true);
9906
9907 // Ensure that capture cannot be disabled from a window that does not have capture.
9908 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
9909 mFakePolicy->assertSetPointerCaptureNotCalled();
9910
9911 // Ensure that capture can be disabled from the window with capture.
9912 requestAndVerifyPointerCapture(mWindow, false);
9913}
9914
9915TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009916 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009917
9918 setFocusedWindow(mSecondWindow);
9919
9920 // Ensure that the capture disabled event was sent first.
9921 mWindow->consumeCaptureEvent(false);
9922 mWindow->consumeFocusEvent(false);
9923 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009924 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009925
9926 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009927 notifyPointerCaptureChanged({});
9928 notifyPointerCaptureChanged(request);
9929 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08009930 mWindow->assertNoEvents();
9931 mSecondWindow->assertNoEvents();
9932 mFakePolicy->assertSetPointerCaptureNotCalled();
9933}
9934
9935TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009936 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009937
9938 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009939 notifyPointerCaptureChanged({});
9940 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009941
9942 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009943 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009944 mWindow->consumeCaptureEvent(false);
9945 mWindow->assertNoEvents();
9946}
9947
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009948TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
9949 requestAndVerifyPointerCapture(mWindow, true);
9950
9951 // The first window loses focus.
9952 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009953 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009954 mWindow->consumeCaptureEvent(false);
9955
9956 // Request Pointer Capture from the second window before the notification from InputReader
9957 // arrives.
9958 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009959 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009960
9961 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009962 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009963
9964 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009965 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009966
9967 mSecondWindow->consumeFocusEvent(true);
9968 mSecondWindow->consumeCaptureEvent(true);
9969}
9970
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009971TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
9972 // App repeatedly enables and disables capture.
9973 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9974 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9975 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9976 mFakePolicy->assertSetPointerCaptureCalled(false);
9977 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9978 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9979
9980 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
9981 // first request is now stale, this should do nothing.
9982 notifyPointerCaptureChanged(firstRequest);
9983 mWindow->assertNoEvents();
9984
9985 // InputReader notifies that the second request was enabled.
9986 notifyPointerCaptureChanged(secondRequest);
9987 mWindow->consumeCaptureEvent(true);
9988}
9989
Prabir Pradhan7092e262022-05-03 16:51:09 +00009990TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
9991 requestAndVerifyPointerCapture(mWindow, true);
9992
9993 // App toggles pointer capture off and on.
9994 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9995 mFakePolicy->assertSetPointerCaptureCalled(false);
9996
9997 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9998 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9999
10000 // InputReader notifies that the latest "enable" request was processed, while skipping over the
10001 // preceding "disable" request.
10002 notifyPointerCaptureChanged(enableRequest);
10003
10004 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
10005 // any notifications.
10006 mWindow->assertNoEvents();
10007}
10008
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010009/**
10010 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
10011 * mouse movements don't affect the previous mouse hovering state.
10012 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
10013 * HOVER_MOVE events).
10014 */
10015TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
10016 // Mouse hover on the window
10017 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
10018 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
10019 .build());
10020 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
10021 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
10022 .build());
10023
10024 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
10025 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
10026
10027 // Start pointer capture
10028 requestAndVerifyPointerCapture(mWindow, true);
10029
10030 // Send some relative mouse movements and receive them in the window.
10031 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
10032 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
10033 .build());
10034 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
10035 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
10036
10037 // Stop pointer capture
10038 requestAndVerifyPointerCapture(mWindow, false);
10039
10040 // Continue hovering on the window
10041 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
10042 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
10043 .build());
10044 mWindow->consumeMotionEvent(
10045 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
10046
10047 mWindow->assertNoEvents();
10048}
10049
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010050class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
10051protected:
10052 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +000010053
10054 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
10055 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
10056
10057 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
10058 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
10059
10060 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
10061 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
10062 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
10063 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
10064 MAXIMUM_OBSCURING_OPACITY);
10065
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010066 static constexpr gui::Uid TOUCHED_APP_UID{10001};
10067 static constexpr gui::Uid APP_B_UID{10002};
10068 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010069
10070 sp<FakeWindowHandle> mTouchWindow;
10071
10072 virtual void SetUp() override {
10073 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010074 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010075 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
10076 }
10077
10078 virtual void TearDown() override {
10079 InputDispatcherTest::TearDown();
10080 mTouchWindow.clear();
10081 }
10082
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010083 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -050010084 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010085 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010086 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010087 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010088 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010089 return window;
10090 }
10091
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010092 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010093 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
10094 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010095 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010096 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010097 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010098 return window;
10099 }
10100
10101 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010102 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10103 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10104 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010105 }
10106};
10107
10108TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010109 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010110 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010111 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010112
10113 touch();
10114
10115 mTouchWindow->assertNoEvents();
10116}
10117
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010118TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +000010119 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
10120 const sp<FakeWindowHandle>& w =
10121 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010122 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010123
10124 touch();
10125
10126 mTouchWindow->assertNoEvents();
10127}
10128
10129TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010130 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
10131 const sp<FakeWindowHandle>& w =
10132 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010133 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010134
10135 touch();
10136
10137 w->assertNoEvents();
10138}
10139
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010140TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010141 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010142 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010143
10144 touch();
10145
10146 mTouchWindow->consumeAnyMotionDown();
10147}
10148
10149TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010150 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010151 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010152 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010153 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010154
10155 touch({PointF{100, 100}});
10156
10157 mTouchWindow->consumeAnyMotionDown();
10158}
10159
10160TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010161 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010162 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010163 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010164
10165 touch();
10166
10167 mTouchWindow->consumeAnyMotionDown();
10168}
10169
10170TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
10171 const sp<FakeWindowHandle>& w =
10172 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
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->consumeAnyMotionDown();
10178}
10179
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010180TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
10181 const sp<FakeWindowHandle>& w =
10182 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010183 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010184
10185 touch();
10186
10187 w->assertNoEvents();
10188}
10189
10190/**
10191 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
10192 * inside) while letting them pass-through. Note that even though touch passes through the occluding
10193 * window, the occluding window will still receive ACTION_OUTSIDE event.
10194 */
10195TEST_F(InputDispatcherUntrustedTouchesTest,
10196 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
10197 const sp<FakeWindowHandle>& w =
10198 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010199 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010200 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010201
10202 touch();
10203
10204 w->consumeMotionOutside();
10205}
10206
10207TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
10208 const sp<FakeWindowHandle>& w =
10209 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010210 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010211 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010212
10213 touch();
10214
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010215 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010216}
10217
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010218TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010219 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010220 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10221 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010222 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010223
10224 touch();
10225
10226 mTouchWindow->consumeAnyMotionDown();
10227}
10228
10229TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
10230 const sp<FakeWindowHandle>& w =
10231 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10232 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010233 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010234
10235 touch();
10236
10237 mTouchWindow->consumeAnyMotionDown();
10238}
10239
10240TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010241 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010242 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10243 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010244 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010245
10246 touch();
10247
10248 mTouchWindow->assertNoEvents();
10249}
10250
10251TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
10252 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
10253 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010254 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
10255 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010256 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010257 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
10258 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010259 mDispatcher->onWindowInfosChanged(
10260 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010261
10262 touch();
10263
10264 mTouchWindow->assertNoEvents();
10265}
10266
10267TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
10268 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
10269 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010270 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
10271 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010272 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010273 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
10274 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010275 mDispatcher->onWindowInfosChanged(
10276 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010277
10278 touch();
10279
10280 mTouchWindow->consumeAnyMotionDown();
10281}
10282
10283TEST_F(InputDispatcherUntrustedTouchesTest,
10284 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
10285 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010286 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10287 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010288 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010289 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10290 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010291 mDispatcher->onWindowInfosChanged(
10292 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010293
10294 touch();
10295
10296 mTouchWindow->consumeAnyMotionDown();
10297}
10298
10299TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
10300 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010301 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10302 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010303 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010304 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10305 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010306 mDispatcher->onWindowInfosChanged(
10307 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010308
10309 touch();
10310
10311 mTouchWindow->assertNoEvents();
10312}
10313
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010314TEST_F(InputDispatcherUntrustedTouchesTest,
10315 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
10316 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010317 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10318 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010319 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010320 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10321 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010322 mDispatcher->onWindowInfosChanged(
10323 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010324
10325 touch();
10326
10327 mTouchWindow->assertNoEvents();
10328}
10329
10330TEST_F(InputDispatcherUntrustedTouchesTest,
10331 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
10332 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010333 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10334 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010335 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010336 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10337 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010338 mDispatcher->onWindowInfosChanged(
10339 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010340
10341 touch();
10342
10343 mTouchWindow->consumeAnyMotionDown();
10344}
10345
10346TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
10347 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010348 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10349 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010350 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010351
10352 touch();
10353
10354 mTouchWindow->consumeAnyMotionDown();
10355}
10356
10357TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
10358 const sp<FakeWindowHandle>& w =
10359 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010360 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010361
10362 touch();
10363
10364 mTouchWindow->consumeAnyMotionDown();
10365}
10366
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010367TEST_F(InputDispatcherUntrustedTouchesTest,
10368 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
10369 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
10370 const sp<FakeWindowHandle>& w =
10371 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010372 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010373
10374 touch();
10375
10376 mTouchWindow->assertNoEvents();
10377}
10378
10379TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
10380 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
10381 const sp<FakeWindowHandle>& w =
10382 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010383 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010384
10385 touch();
10386
10387 mTouchWindow->consumeAnyMotionDown();
10388}
10389
10390TEST_F(InputDispatcherUntrustedTouchesTest,
10391 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
10392 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
10393 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010394 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10395 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010396 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010397
10398 touch();
10399
10400 mTouchWindow->consumeAnyMotionDown();
10401}
10402
10403TEST_F(InputDispatcherUntrustedTouchesTest,
10404 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
10405 const sp<FakeWindowHandle>& w1 =
10406 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
10407 OPACITY_BELOW_THRESHOLD);
10408 const sp<FakeWindowHandle>& w2 =
10409 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10410 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010411 mDispatcher->onWindowInfosChanged(
10412 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010413
10414 touch();
10415
10416 mTouchWindow->assertNoEvents();
10417}
10418
10419/**
10420 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
10421 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
10422 * (which alone would result in allowing touches) does not affect the blocking behavior.
10423 */
10424TEST_F(InputDispatcherUntrustedTouchesTest,
10425 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
10426 const sp<FakeWindowHandle>& wB =
10427 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
10428 OPACITY_BELOW_THRESHOLD);
10429 const sp<FakeWindowHandle>& wC =
10430 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10431 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010432 mDispatcher->onWindowInfosChanged(
10433 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010434
10435 touch();
10436
10437 mTouchWindow->assertNoEvents();
10438}
10439
10440/**
10441 * This test is testing that a window from a different UID but with same application token doesn't
10442 * block the touch. Apps can share the application token for close UI collaboration for example.
10443 */
10444TEST_F(InputDispatcherUntrustedTouchesTest,
10445 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
10446 const sp<FakeWindowHandle>& w =
10447 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
10448 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010449 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010450
10451 touch();
10452
10453 mTouchWindow->consumeAnyMotionDown();
10454}
10455
arthurhungb89ccb02020-12-30 16:19:01 +080010456class InputDispatcherDragTests : public InputDispatcherTest {
10457protected:
10458 std::shared_ptr<FakeApplicationHandle> mApp;
10459 sp<FakeWindowHandle> mWindow;
10460 sp<FakeWindowHandle> mSecondWindow;
10461 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010462 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010463 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
10464 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +080010465
10466 void SetUp() override {
10467 InputDispatcherTest::SetUp();
10468 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010469 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080010470 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080010471
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010472 mSecondWindow =
10473 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080010474 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080010475
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010476 mSpyWindow =
10477 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010478 mSpyWindow->setSpy(true);
10479 mSpyWindow->setTrustedOverlay(true);
10480 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
10481
arthurhungb89ccb02020-12-30 16:19:01 +080010482 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010483 mDispatcher->onWindowInfosChanged(
10484 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
10485 {},
10486 0,
10487 0});
arthurhungb89ccb02020-12-30 16:19:01 +080010488 }
10489
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010490 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
10491 switch (fromSource) {
10492 case AINPUT_SOURCE_TOUCHSCREEN:
10493 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010494 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010495 ADISPLAY_ID_DEFAULT, {50, 50}))
10496 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10497 break;
10498 case AINPUT_SOURCE_STYLUS:
10499 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010500 injectMotionEvent(*mDispatcher,
10501 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10502 AINPUT_SOURCE_STYLUS)
10503 .buttonState(
10504 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
10505 .pointer(PointerBuilder(0, ToolType::STYLUS)
10506 .x(50)
10507 .y(50))
10508 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010509 break;
10510 case AINPUT_SOURCE_MOUSE:
10511 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010512 injectMotionEvent(*mDispatcher,
10513 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10514 AINPUT_SOURCE_MOUSE)
10515 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
10516 .pointer(PointerBuilder(MOUSE_POINTER_ID,
10517 ToolType::MOUSE)
10518 .x(50)
10519 .y(50))
10520 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010521 break;
10522 default:
10523 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
10524 }
arthurhungb89ccb02020-12-30 16:19:01 +080010525
10526 // Window should receive motion event.
10527 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010528 // Spy window should also receive motion event
10529 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000010530 }
10531
10532 // Start performing drag, we will create a drag window and transfer touch to it.
10533 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
10534 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010535 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +000010536 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010537 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +000010538 }
arthurhungb89ccb02020-12-30 16:19:01 +080010539
10540 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010541 mDragWindow =
10542 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010543 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010544 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
10545 *mWindow->getInfo(), *mSecondWindow->getInfo()},
10546 {},
10547 0,
10548 0});
arthurhungb89ccb02020-12-30 16:19:01 +080010549
10550 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +000010551 bool transferred =
Prabir Pradhan367f3432024-02-13 23:05:58 +000010552 mDispatcher->transferTouchGesture(mWindow->getToken(), mDragWindow->getToken(),
10553 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +000010554 if (transferred) {
10555 mWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +000010556 mDragWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000010557 }
10558 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +080010559 }
10560};
10561
10562TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010563 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +080010564
10565 // Move on window.
10566 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010567 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010568 ADISPLAY_ID_DEFAULT, {50, 50}))
10569 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010570 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080010571 mWindow->consumeDragEvent(false, 50, 50);
10572 mSecondWindow->assertNoEvents();
10573
10574 // Move to another window.
10575 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010576 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010577 ADISPLAY_ID_DEFAULT, {150, 50}))
10578 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010579 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080010580 mWindow->consumeDragEvent(true, 150, 50);
10581 mSecondWindow->consumeDragEvent(false, 50, 50);
10582
10583 // Move back to original window.
10584 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010585 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010586 ADISPLAY_ID_DEFAULT, {50, 50}))
10587 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010588 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080010589 mWindow->consumeDragEvent(false, 50, 50);
10590 mSecondWindow->consumeDragEvent(true, -50, 50);
10591
10592 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010593 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10594 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080010595 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010596 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080010597 mWindow->assertNoEvents();
10598 mSecondWindow->assertNoEvents();
10599}
10600
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010601TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010602 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010603
10604 // No cancel event after drag start
10605 mSpyWindow->assertNoEvents();
10606
10607 const MotionEvent secondFingerDownEvent =
10608 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10609 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010610 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10611 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010612 .build();
10613 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010614 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010615 InputEventInjectionSync::WAIT_FOR_RESULT))
10616 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10617
10618 // Receives cancel for first pointer after next pointer down
10619 mSpyWindow->consumeMotionCancel();
10620 mSpyWindow->consumeMotionDown();
10621
10622 mSpyWindow->assertNoEvents();
10623}
10624
arthurhungf452d0b2021-01-06 00:19:52 +080010625TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010626 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +080010627
10628 // Move on window.
10629 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010630 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +080010631 ADISPLAY_ID_DEFAULT, {50, 50}))
10632 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010633 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080010634 mWindow->consumeDragEvent(false, 50, 50);
10635 mSecondWindow->assertNoEvents();
10636
10637 // Move to another window.
10638 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010639 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +080010640 ADISPLAY_ID_DEFAULT, {150, 50}))
10641 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010642 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080010643 mWindow->consumeDragEvent(true, 150, 50);
10644 mSecondWindow->consumeDragEvent(false, 50, 50);
10645
10646 // drop to another window.
10647 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010648 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +080010649 {150, 50}))
10650 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010651 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010652 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +080010653 mWindow->assertNoEvents();
10654 mSecondWindow->assertNoEvents();
10655}
10656
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010657TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
10658 startDrag();
10659
10660 // No cancel event after drag start
10661 mSpyWindow->assertNoEvents();
10662
10663 const MotionEvent secondFingerDownEvent =
10664 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10665 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10666 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10667 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10668 .build();
10669 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10670 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10671 InputEventInjectionSync::WAIT_FOR_RESULT))
10672 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10673
10674 // Receives cancel for first pointer after next pointer down
10675 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080010676 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010677 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
10678
10679 mSpyWindow->assertNoEvents();
10680
10681 // Spy window calls pilfer pointers
10682 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
10683 mDragWindow->assertNoEvents();
10684
10685 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010686 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010687 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10688 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
10689 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10690 .build();
10691 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010692 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010693 InputEventInjectionSync::WAIT_FOR_RESULT))
10694 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10695
10696 // Drag window should still receive the new event
Prabir Pradhan65455c72024-02-13 21:46:41 +000010697 mDragWindow->consumeMotionEvent(
10698 AllOf(WithMotionAction(ACTION_MOVE), WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010699 mDragWindow->assertNoEvents();
10700}
10701
arthurhung6d4bed92021-03-17 11:59:33 +080010702TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010703 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +080010704
10705 // Move on window and keep button pressed.
10706 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010707 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010708 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10709 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010710 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010711 .build()))
10712 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010713 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080010714 mWindow->consumeDragEvent(false, 50, 50);
10715 mSecondWindow->assertNoEvents();
10716
10717 // Move to another window and release button, expect to drop item.
10718 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010719 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010720 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10721 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010722 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010723 .build()))
10724 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010725 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080010726 mWindow->assertNoEvents();
10727 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010728 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +080010729
10730 // nothing to the window.
10731 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010732 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010733 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
10734 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010735 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010736 .build()))
10737 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010738 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080010739 mWindow->assertNoEvents();
10740 mSecondWindow->assertNoEvents();
10741}
10742
Arthur Hung54745652022-04-20 07:17:41 +000010743TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010744 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +080010745
10746 // Set second window invisible.
10747 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010748 mDispatcher->onWindowInfosChanged(
10749 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +080010750
10751 // Move on window.
10752 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010753 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010754 ADISPLAY_ID_DEFAULT, {50, 50}))
10755 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010756 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010757 mWindow->consumeDragEvent(false, 50, 50);
10758 mSecondWindow->assertNoEvents();
10759
10760 // Move to another window.
10761 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010762 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010763 ADISPLAY_ID_DEFAULT, {150, 50}))
10764 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010765 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010766 mWindow->consumeDragEvent(true, 150, 50);
10767 mSecondWindow->assertNoEvents();
10768
10769 // drop to another window.
10770 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010771 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010772 {150, 50}))
10773 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010774 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010775 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010776 mWindow->assertNoEvents();
10777 mSecondWindow->assertNoEvents();
10778}
10779
Arthur Hung54745652022-04-20 07:17:41 +000010780TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010781 // Ensure window could track pointerIds if it didn't support split touch.
10782 mWindow->setPreventSplitting(true);
10783
Arthur Hung54745652022-04-20 07:17:41 +000010784 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010785 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010786 {50, 50}))
10787 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10788 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10789
10790 const MotionEvent secondFingerDownEvent =
10791 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10792 .displayId(ADISPLAY_ID_DEFAULT)
10793 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010794 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10795 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010796 .build();
10797 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010798 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010799 InputEventInjectionSync::WAIT_FOR_RESULT))
10800 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010801 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +000010802
10803 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010804 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010805}
10806
10807TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
10808 // First down on second window.
10809 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010810 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010811 {150, 50}))
10812 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10813
10814 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10815
10816 // Second down on first window.
10817 const MotionEvent secondFingerDownEvent =
10818 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10819 .displayId(ADISPLAY_ID_DEFAULT)
10820 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010821 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10822 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010823 .build();
10824 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010825 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010826 InputEventInjectionSync::WAIT_FOR_RESULT))
10827 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10828 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +000010829 mSecondWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000010830
10831 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010832 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010833
10834 // Move on window.
10835 const MotionEvent secondFingerMoveEvent =
10836 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10837 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010838 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10839 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010840 .build();
10841 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010842 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010843 InputEventInjectionSync::WAIT_FOR_RESULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +000010844 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000010845 mWindow->consumeDragEvent(false, 50, 50);
10846 mSecondWindow->consumeMotionMove();
10847
10848 // Release the drag pointer should perform drop.
10849 const MotionEvent secondFingerUpEvent =
10850 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10851 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010852 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10853 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010854 .build();
10855 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010856 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010857 InputEventInjectionSync::WAIT_FOR_RESULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +000010858 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010859 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000010860 mWindow->assertNoEvents();
10861 mSecondWindow->consumeMotionMove();
10862}
10863
Arthur Hung3915c1f2022-05-31 07:17:17 +000010864TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010865 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000010866
10867 // Update window of second display.
10868 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010869 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010870 mDispatcher->onWindowInfosChanged(
10871 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10872 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10873 {},
10874 0,
10875 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010876
10877 // Let second display has a touch state.
10878 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010879 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010880 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10881 AINPUT_SOURCE_TOUCHSCREEN)
10882 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010883 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000010884 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000010885 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010886 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010887 mDispatcher->onWindowInfosChanged(
10888 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10889 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10890 {},
10891 0,
10892 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010893
10894 // Move on window.
10895 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010896 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010897 ADISPLAY_ID_DEFAULT, {50, 50}))
10898 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010899 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010900 mWindow->consumeDragEvent(false, 50, 50);
10901 mSecondWindow->assertNoEvents();
10902
10903 // Move to another window.
10904 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010905 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010906 ADISPLAY_ID_DEFAULT, {150, 50}))
10907 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010908 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010909 mWindow->consumeDragEvent(true, 150, 50);
10910 mSecondWindow->consumeDragEvent(false, 50, 50);
10911
10912 // drop to another window.
10913 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010914 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010915 {150, 50}))
10916 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010917 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010918 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000010919 mWindow->assertNoEvents();
10920 mSecondWindow->assertNoEvents();
10921}
10922
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010923TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
10924 startDrag(true, AINPUT_SOURCE_MOUSE);
10925 // Move on window.
10926 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010927 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010928 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10929 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010930 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010931 .x(50)
10932 .y(50))
10933 .build()))
10934 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010935 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010936 mWindow->consumeDragEvent(false, 50, 50);
10937 mSecondWindow->assertNoEvents();
10938
10939 // Move to another window.
10940 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010941 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010942 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10943 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010944 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010945 .x(150)
10946 .y(50))
10947 .build()))
10948 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010949 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010950 mWindow->consumeDragEvent(true, 150, 50);
10951 mSecondWindow->consumeDragEvent(false, 50, 50);
10952
10953 // drop to another window.
10954 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010955 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010956 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
10957 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010958 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010959 .x(150)
10960 .y(50))
10961 .build()))
10962 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010963 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010964 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010965 mWindow->assertNoEvents();
10966 mSecondWindow->assertNoEvents();
10967}
10968
Linnan Li5af92f92023-07-14 14:36:22 +080010969/**
10970 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
10971 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
10972 */
10973TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
10974 // Down on second window
10975 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10976 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10977 {150, 50}))
10978 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10979
10980 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
10981 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
10982
10983 // Down on first window
10984 const MotionEvent secondFingerDownEvent =
10985 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10986 .displayId(ADISPLAY_ID_DEFAULT)
10987 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10988 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10989 .build();
10990 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10991 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10992 InputEventInjectionSync::WAIT_FOR_RESULT))
10993 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10994 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10995 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
10996 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
10997
10998 // Start drag on first window
10999 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
11000
11001 // Trigger cancel
11002 mDispatcher->cancelCurrentTouch();
11003 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
Prabir Pradhan65455c72024-02-13 21:46:41 +000011004 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT,
11005 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE));
Linnan Li5af92f92023-07-14 14:36:22 +080011006 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
11007
11008 ASSERT_TRUE(mDispatcher->waitForIdle());
11009 // The D&D finished with nullptr
11010 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
11011
11012 // Remove drag window
11013 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
11014
11015 // Inject a simple gesture, ensure dispatcher not crashed
11016 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11017 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
11018 PointF{50, 50}))
11019 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11020 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
11021
11022 const MotionEvent moveEvent =
11023 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
11024 .displayId(ADISPLAY_ID_DEFAULT)
11025 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11026 .build();
11027 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11028 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
11029 InputEventInjectionSync::WAIT_FOR_RESULT))
11030 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11031 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
11032
11033 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11034 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
11035 {50, 50}))
11036 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11037 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
11038}
11039
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000011040TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
11041 // Start hovering over the window.
11042 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11043 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
11044 ADISPLAY_ID_DEFAULT, {50, 50}));
11045
11046 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
11047 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
11048
11049 ASSERT_FALSE(startDrag(/*sendDown=*/false))
11050 << "Drag and drop should not work with a hovering pointer";
11051}
11052
Vishnu Nair062a8672021-09-03 16:07:44 -070011053class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
11054
11055TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
11056 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011057 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
11058 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011059 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011060 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
11061 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011062 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011063 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011064 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011065
11066 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000011067 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011068 window->assertNoEvents();
11069
Prabir Pradhan678438e2023-04-13 19:32:51 +000011070 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11071 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070011072 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
11073 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080011074 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070011075 window->assertNoEvents();
11076
11077 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011078 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011079 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011080
Prabir Pradhan678438e2023-04-13 19:32:51 +000011081 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011082 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
11083
Prabir Pradhan678438e2023-04-13 19:32:51 +000011084 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11085 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011086 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11087 window->assertNoEvents();
11088}
11089
11090TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
11091 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
11092 std::make_shared<FakeApplicationHandle>();
11093 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011094 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
11095 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070011096 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011097 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011098 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070011099 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011100 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
11101 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011102 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011103 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070011104 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
11105 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011106 mDispatcher->onWindowInfosChanged(
11107 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011108 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011109 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011110
11111 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000011112 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011113 window->assertNoEvents();
11114
Prabir Pradhan678438e2023-04-13 19:32:51 +000011115 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11116 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070011117 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
11118 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011119 window->assertNoEvents();
11120
11121 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011122 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011123 mDispatcher->onWindowInfosChanged(
11124 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011125
Prabir Pradhan678438e2023-04-13 19:32:51 +000011126 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011127 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
11128
Prabir Pradhan678438e2023-04-13 19:32:51 +000011129 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11130 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011131 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
11132 window->assertNoEvents();
11133}
11134
11135TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
11136 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
11137 std::make_shared<FakeApplicationHandle>();
11138 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011139 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
11140 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070011141 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011142 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011143 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070011144 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011145 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
11146 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011147 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011148 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070011149 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
11150 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011151 mDispatcher->onWindowInfosChanged(
11152 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011153 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011154 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011155
11156 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000011157 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011158 window->assertNoEvents();
11159
Prabir Pradhan678438e2023-04-13 19:32:51 +000011160 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11161 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070011162 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
11163 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011164 window->assertNoEvents();
11165
11166 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011167 mDispatcher->onWindowInfosChanged(
11168 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011169
Prabir Pradhan678438e2023-04-13 19:32:51 +000011170 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011171 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
11172
Prabir Pradhan678438e2023-04-13 19:32:51 +000011173 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11174 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011175 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11176 window->assertNoEvents();
11177}
11178
Antonio Kantekf16f2832021-09-28 04:39:20 +000011179class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
11180protected:
11181 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000011182 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000011183 sp<FakeWindowHandle> mWindow;
11184 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000011185 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000011186
11187 void SetUp() override {
11188 InputDispatcherTest::SetUp();
11189
11190 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000011191 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011192 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011193 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011194 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011195 mSecondWindow =
11196 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011197 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000011198 mThirdWindow =
11199 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
11200 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
11201 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011202
11203 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011204 mDispatcher->onWindowInfosChanged(
11205 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
11206 {},
11207 0,
11208 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000011209 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011210 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011211
Antonio Kantek15beb512022-06-13 22:35:41 +000011212 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000011213 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000011214 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070011215 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
11216 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000011217 mThirdWindow->assertNoEvents();
11218 }
11219
11220 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
11221 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000011222 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000011223 SECOND_DISPLAY_ID)) {
11224 mWindow->assertNoEvents();
11225 mSecondWindow->assertNoEvents();
11226 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070011227 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000011228 }
11229
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011230 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000011231 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070011232 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
11233 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000011234 mWindow->consumeTouchModeEvent(inTouchMode);
11235 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000011236 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000011237 }
11238};
11239
Antonio Kantek26defcf2022-02-08 01:12:27 +000011240TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080011241 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000011242 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
11243 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011244 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011245}
11246
Antonio Kantek26defcf2022-02-08 01:12:27 +000011247TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
11248 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011249 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011250 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011251 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011252 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000011253 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -070011254 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000011255 mWindow->assertNoEvents();
11256 mSecondWindow->assertNoEvents();
11257}
11258
11259TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
11260 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011261 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011262 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011263 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000011264 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000011265 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011266}
11267
Antonio Kantekf16f2832021-09-28 04:39:20 +000011268TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080011269 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000011270 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
11271 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011272 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000011273 mWindow->assertNoEvents();
11274 mSecondWindow->assertNoEvents();
11275}
11276
Antonio Kantek15beb512022-06-13 22:35:41 +000011277TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
11278 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
11279 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
11280 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011281 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000011282 mWindow->assertNoEvents();
11283 mSecondWindow->assertNoEvents();
11284 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
11285}
11286
Antonio Kantek48710e42022-03-24 14:19:30 -070011287TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
11288 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011289 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11290 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070011291 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11292 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
11293
11294 // Then remove focus.
11295 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011296 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070011297
11298 // Assert that caller can switch touch mode by owning one of the last interacted window.
11299 const WindowInfo& windowInfo = *mWindow->getInfo();
11300 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
11301 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011302 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070011303}
11304
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011305class InputDispatcherSpyWindowTest : public InputDispatcherTest {
11306public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011307 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011308 std::shared_ptr<FakeApplicationHandle> application =
11309 std::make_shared<FakeApplicationHandle>();
11310 std::string name = "Fake Spy ";
11311 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011312 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
11313 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011314 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011315 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011316 return spy;
11317 }
11318
11319 sp<FakeWindowHandle> createForeground() {
11320 std::shared_ptr<FakeApplicationHandle> application =
11321 std::make_shared<FakeApplicationHandle>();
11322 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011323 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
11324 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011325 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011326 return window;
11327 }
11328
11329private:
11330 int mSpyCount{0};
11331};
11332
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011333using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011334/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011335 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
11336 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011337TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070011338 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011339 ScopedSilentDeath _silentDeath;
11340
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011341 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011342 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011343 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011344 ".* not a trusted overlay");
11345}
11346
11347/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011348 * Input injection into a display with a spy window but no foreground windows should succeed.
11349 */
11350TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011351 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011352 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011353
11354 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011355 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011356 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11357 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11358}
11359
11360/**
11361 * Verify the order in which different input windows receive events. The touched foreground window
11362 * (if there is one) should always receive the event first. When there are multiple spy windows, the
11363 * spy windows will receive the event according to their Z-order, where the top-most spy window will
11364 * receive events before ones belows it.
11365 *
11366 * Here, we set up a scenario with four windows in the following Z order from the top:
11367 * spy1, spy2, window, spy3.
11368 * We then inject an event and verify that the foreground "window" receives it first, followed by
11369 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
11370 * window.
11371 */
11372TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
11373 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011374 auto spy1 = createSpy();
11375 auto spy2 = createSpy();
11376 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011377 mDispatcher->onWindowInfosChanged(
11378 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011379 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
11380 const size_t numChannels = channels.size();
11381
Michael Wright8e9a8562022-02-09 13:44:29 +000011382 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011383 if (!epollFd.ok()) {
11384 FAIL() << "Failed to create epoll fd";
11385 }
11386
11387 for (size_t i = 0; i < numChannels; i++) {
11388 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
11389 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
11390 FAIL() << "Failed to add fd to epoll";
11391 }
11392 }
11393
11394 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011395 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011396 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11397
11398 std::vector<size_t> eventOrder;
11399 std::vector<struct epoll_event> events(numChannels);
11400 for (;;) {
11401 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
11402 (100ms).count());
11403 if (nFds < 0) {
11404 FAIL() << "Failed to call epoll_wait";
11405 }
11406 if (nFds == 0) {
11407 break; // epoll_wait timed out
11408 }
11409 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070011410 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070011411 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011412 channels[i]->consumeMotionDown();
11413 }
11414 }
11415
11416 // Verify the order in which the events were received.
11417 EXPECT_EQ(3u, eventOrder.size());
11418 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
11419 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
11420 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
11421}
11422
11423/**
11424 * A spy window using the NOT_TOUCHABLE flag does not receive events.
11425 */
11426TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
11427 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011428 auto spy = createSpy();
11429 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011430 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011431
11432 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011433 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011434 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11435 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11436 spy->assertNoEvents();
11437}
11438
11439/**
11440 * A spy window will only receive gestures that originate within its touchable region. Gestures that
11441 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
11442 * to the window.
11443 */
11444TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
11445 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011446 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011447 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011448 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011449
11450 // Inject an event outside the spy window's touchable region.
11451 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011452 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011453 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11454 window->consumeMotionDown();
11455 spy->assertNoEvents();
11456 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011457 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011458 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11459 window->consumeMotionUp();
11460 spy->assertNoEvents();
11461
11462 // Inject an event inside the spy window's touchable region.
11463 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011464 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011465 {5, 10}))
11466 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11467 window->consumeMotionDown();
11468 spy->consumeMotionDown();
11469}
11470
11471/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011472 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011473 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011474 */
11475TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
11476 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011477 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011478 auto spy = createSpy();
11479 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011480 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011481 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011482 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011483
11484 // Inject an event outside the spy window's frame and touchable region.
11485 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011486 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011487 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011488 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11489 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011490 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011491}
11492
11493/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011494 * Even when a spy window spans over multiple foreground windows, the spy should receive all
11495 * pointers that are down within its bounds.
11496 */
11497TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
11498 auto windowLeft = createForeground();
11499 windowLeft->setFrame({0, 0, 100, 200});
11500 auto windowRight = createForeground();
11501 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011502 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011503 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011504 mDispatcher->onWindowInfosChanged(
11505 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011506
11507 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011508 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011509 {50, 50}))
11510 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11511 windowLeft->consumeMotionDown();
11512 spy->consumeMotionDown();
11513
11514 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011515 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011516 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011517 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11518 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011519 .build();
11520 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011521 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011522 InputEventInjectionSync::WAIT_FOR_RESULT))
11523 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11524 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000011525 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011526}
11527
11528/**
11529 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
11530 * the spy should receive the second pointer with ACTION_DOWN.
11531 */
11532TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
11533 auto window = createForeground();
11534 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011535 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011536 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011537 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011538
11539 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011540 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011541 {50, 50}))
11542 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11543 window->consumeMotionDown();
11544 spyRight->assertNoEvents();
11545
11546 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011547 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011548 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011549 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11550 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011551 .build();
11552 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011553 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011554 InputEventInjectionSync::WAIT_FOR_RESULT))
11555 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000011556 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011557 spyRight->consumeMotionDown();
11558}
11559
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011560/**
11561 * The spy window should not be able to affect whether or not touches are split. Only the foreground
11562 * windows should be allowed to control split touch.
11563 */
11564TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080011565 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011566 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011567 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080011568 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011569
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011570 auto window = createForeground();
11571 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011572
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011573 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011574
11575 // First finger down, no window touched.
11576 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011577 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011578 {100, 200}))
11579 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11580 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11581 window->assertNoEvents();
11582
11583 // Second finger down on window, the window should receive touch down.
11584 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011585 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011586 .displayId(ADISPLAY_ID_DEFAULT)
11587 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011588 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11589 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011590 .build();
11591 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011592 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011593 InputEventInjectionSync::WAIT_FOR_RESULT))
11594 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11595
11596 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000011597 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011598}
11599
11600/**
11601 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
11602 * do not receive key events.
11603 */
11604TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011605 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011606 spy->setFocusable(false);
11607
11608 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011609 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011610 setFocusedWindow(window);
11611 window->consumeFocusEvent(true);
11612
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011613 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011614 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11615 window->consumeKeyDown(ADISPLAY_ID_NONE);
11616
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011617 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011618 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11619 window->consumeKeyUp(ADISPLAY_ID_NONE);
11620
11621 spy->assertNoEvents();
11622}
11623
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011624using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
11625
11626/**
11627 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
11628 * are currently sent to any other windows - including other spy windows - will also be cancelled.
11629 */
11630TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
11631 auto window = createForeground();
11632 auto spy1 = createSpy();
11633 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011634 mDispatcher->onWindowInfosChanged(
11635 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011636
11637 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011638 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011639 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11640 window->consumeMotionDown();
11641 spy1->consumeMotionDown();
11642 spy2->consumeMotionDown();
11643
11644 // Pilfer pointers from the second spy window.
11645 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
11646 spy2->assertNoEvents();
11647 spy1->consumeMotionCancel();
11648 window->consumeMotionCancel();
11649
11650 // The rest of the gesture should only be sent to the second spy window.
11651 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011652 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011653 ADISPLAY_ID_DEFAULT))
11654 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11655 spy2->consumeMotionMove();
11656 spy1->assertNoEvents();
11657 window->assertNoEvents();
11658}
11659
11660/**
11661 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
11662 * in the middle of the gesture.
11663 */
11664TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
11665 auto window = createForeground();
11666 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011667 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011668
11669 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011670 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011671 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11672 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11673 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11674
11675 window->releaseChannel();
11676
11677 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11678
11679 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011680 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011681 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11682 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
11683}
11684
11685/**
11686 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
11687 * the spy, but not to any other windows.
11688 */
11689TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
11690 auto spy = createSpy();
11691 auto window = createForeground();
11692
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011693 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011694
11695 // First finger down on the window and the spy.
11696 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011697 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011698 {100, 200}))
11699 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11700 spy->consumeMotionDown();
11701 window->consumeMotionDown();
11702
11703 // Spy window pilfers the pointers.
11704 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11705 window->consumeMotionCancel();
11706
11707 // Second finger down on the window and spy, but the window should not receive the pointer down.
11708 const MotionEvent secondFingerDownEvent =
11709 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11710 .displayId(ADISPLAY_ID_DEFAULT)
11711 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011712 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11713 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011714 .build();
11715 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011716 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011717 InputEventInjectionSync::WAIT_FOR_RESULT))
11718 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11719
Harry Cutts33476232023-01-30 19:57:29 +000011720 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011721
11722 // Third finger goes down outside all windows, so injection should fail.
11723 const MotionEvent thirdFingerDownEvent =
11724 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11725 .displayId(ADISPLAY_ID_DEFAULT)
11726 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011727 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11728 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
11729 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011730 .build();
11731 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011732 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011733 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080011734 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011735
11736 spy->assertNoEvents();
11737 window->assertNoEvents();
11738}
11739
11740/**
11741 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
11742 */
11743TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
11744 auto spy = createSpy();
11745 spy->setFrame(Rect(0, 0, 100, 100));
11746 auto window = createForeground();
11747 window->setFrame(Rect(0, 0, 200, 200));
11748
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011749 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011750
11751 // First finger down on the window only
11752 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011753 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011754 {150, 150}))
11755 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11756 window->consumeMotionDown();
11757
11758 // Second finger down on the spy and window
11759 const MotionEvent secondFingerDownEvent =
11760 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11761 .displayId(ADISPLAY_ID_DEFAULT)
11762 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011763 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11764 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011765 .build();
11766 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011767 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011768 InputEventInjectionSync::WAIT_FOR_RESULT))
11769 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11770 spy->consumeMotionDown();
11771 window->consumeMotionPointerDown(1);
11772
11773 // Third finger down on the spy and window
11774 const MotionEvent thirdFingerDownEvent =
11775 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11776 .displayId(ADISPLAY_ID_DEFAULT)
11777 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011778 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11779 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
11780 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011781 .build();
11782 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011783 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011784 InputEventInjectionSync::WAIT_FOR_RESULT))
11785 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11786 spy->consumeMotionPointerDown(1);
11787 window->consumeMotionPointerDown(2);
11788
11789 // Spy window pilfers the pointers.
11790 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000011791 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
11792 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011793
11794 spy->assertNoEvents();
11795 window->assertNoEvents();
11796}
11797
11798/**
11799 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
11800 * other windows should be canceled. If this results in the cancellation of all pointers for some
11801 * window, then that window should receive ACTION_CANCEL.
11802 */
11803TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
11804 auto spy = createSpy();
11805 spy->setFrame(Rect(0, 0, 100, 100));
11806 auto window = createForeground();
11807 window->setFrame(Rect(0, 0, 200, 200));
11808
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011809 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011810
11811 // First finger down on both spy and window
11812 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011813 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011814 {10, 10}))
11815 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11816 window->consumeMotionDown();
11817 spy->consumeMotionDown();
11818
11819 // Second finger down on the spy and window
11820 const MotionEvent secondFingerDownEvent =
11821 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11822 .displayId(ADISPLAY_ID_DEFAULT)
11823 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011824 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11825 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011826 .build();
11827 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011828 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011829 InputEventInjectionSync::WAIT_FOR_RESULT))
11830 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11831 spy->consumeMotionPointerDown(1);
11832 window->consumeMotionPointerDown(1);
11833
11834 // Spy window pilfers the pointers.
11835 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11836 window->consumeMotionCancel();
11837
11838 spy->assertNoEvents();
11839 window->assertNoEvents();
11840}
11841
11842/**
11843 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
11844 * be sent to other windows
11845 */
11846TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
11847 auto spy = createSpy();
11848 spy->setFrame(Rect(0, 0, 100, 100));
11849 auto window = createForeground();
11850 window->setFrame(Rect(0, 0, 200, 200));
11851
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011852 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011853
11854 // First finger down on both window and spy
11855 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011856 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011857 {10, 10}))
11858 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11859 window->consumeMotionDown();
11860 spy->consumeMotionDown();
11861
11862 // Spy window pilfers the pointers.
11863 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11864 window->consumeMotionCancel();
11865
11866 // Second finger down on the window only
11867 const MotionEvent secondFingerDownEvent =
11868 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11869 .displayId(ADISPLAY_ID_DEFAULT)
11870 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011871 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11872 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011873 .build();
11874 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011875 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011876 InputEventInjectionSync::WAIT_FOR_RESULT))
11877 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11878 window->consumeMotionDown();
11879 window->assertNoEvents();
11880
11881 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
11882 spy->consumeMotionMove();
11883 spy->assertNoEvents();
11884}
11885
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011886/**
11887 * A window on the left and a window on the right. Also, a spy window that's above all of the
11888 * windows, and spanning both left and right windows.
11889 * Send simultaneous motion streams from two different devices, one to the left window, and another
11890 * to the right window.
11891 * Pilfer from spy window.
11892 * Check that the pilfering only affects the pointers that are actually being received by the spy.
11893 */
11894TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
11895 sp<FakeWindowHandle> spy = createSpy();
11896 spy->setFrame(Rect(0, 0, 200, 200));
11897 sp<FakeWindowHandle> leftWindow = createForeground();
11898 leftWindow->setFrame(Rect(0, 0, 100, 100));
11899
11900 sp<FakeWindowHandle> rightWindow = createForeground();
11901 rightWindow->setFrame(Rect(100, 0, 200, 100));
11902
11903 constexpr int32_t stylusDeviceId = 1;
11904 constexpr int32_t touchDeviceId = 2;
11905
11906 mDispatcher->onWindowInfosChanged(
11907 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
11908
11909 // Stylus down on left window and spy
11910 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
11911 .deviceId(stylusDeviceId)
11912 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
11913 .build());
11914 leftWindow->consumeMotionEvent(
11915 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11916 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11917
11918 // Finger down on right window and spy - but spy already has stylus
11919 mDispatcher->notifyMotion(
11920 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11921 .deviceId(touchDeviceId)
11922 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
11923 .build());
11924 rightWindow->consumeMotionEvent(
11925 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011926 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011927
11928 // Act: pilfer from spy. Spy is currently receiving touch events.
11929 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011930 leftWindow->consumeMotionEvent(
11931 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011932 rightWindow->consumeMotionEvent(
11933 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
11934
11935 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
11936 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
11937 .deviceId(stylusDeviceId)
11938 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
11939 .build());
11940 mDispatcher->notifyMotion(
11941 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
11942 .deviceId(touchDeviceId)
11943 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
11944 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011945 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011946
11947 spy->assertNoEvents();
11948 leftWindow->assertNoEvents();
11949 rightWindow->assertNoEvents();
11950}
11951
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000011952TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
11953 auto window = createForeground();
11954 auto spy = createSpy();
11955 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
11956
11957 mDispatcher->notifyMotion(
11958 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11959 .deviceId(1)
11960 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
11961 .build());
11962 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11963 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11964
11965 // Pilfer pointers from the spy window should fail.
11966 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
11967 spy->assertNoEvents();
11968 window->assertNoEvents();
11969}
11970
Prabir Pradhand65552b2021-10-07 11:23:50 -070011971class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
11972public:
11973 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
11974 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11975 std::make_shared<FakeApplicationHandle>();
11976 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011977 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11978 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011979 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011980 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011981 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011982 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011983 overlay->setTrustedOverlay(true);
11984
11985 std::shared_ptr<FakeApplicationHandle> application =
11986 std::make_shared<FakeApplicationHandle>();
11987 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011988 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
11989 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011990 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011991 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011992
11993 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011994 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011995 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011996 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011997 return {std::move(overlay), std::move(window)};
11998 }
11999
12000 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000012001 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070012002 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000012003 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070012004 }
12005
12006 void sendStylusEvent(int32_t action) {
12007 NotifyMotionArgs motionArgs =
12008 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
12009 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012010 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000012011 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070012012 }
12013};
12014
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012015using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
12016
12017TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070012018 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012019 ScopedSilentDeath _silentDeath;
12020
Prabir Pradhand65552b2021-10-07 11:23:50 -070012021 auto [overlay, window] = setupStylusOverlayScenario();
12022 overlay->setTrustedOverlay(false);
12023 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012024 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
12025 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070012026 ".* not a trusted overlay");
12027}
12028
12029TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
12030 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012031 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070012032
12033 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
12034 overlay->consumeMotionDown();
12035 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
12036 overlay->consumeMotionUp();
12037
12038 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
12039 window->consumeMotionDown();
12040 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
12041 window->consumeMotionUp();
12042
12043 overlay->assertNoEvents();
12044 window->assertNoEvents();
12045}
12046
12047TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
12048 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012049 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012050 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070012051
12052 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
12053 overlay->consumeMotionDown();
12054 window->consumeMotionDown();
12055 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
12056 overlay->consumeMotionUp();
12057 window->consumeMotionUp();
12058
12059 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
12060 window->consumeMotionDown();
12061 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
12062 window->consumeMotionUp();
12063
12064 overlay->assertNoEvents();
12065 window->assertNoEvents();
12066}
12067
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000012068/**
12069 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
12070 * The scenario is as follows:
12071 * - The stylus interceptor overlay is configured as a spy window.
12072 * - The stylus interceptor spy receives the start of a new stylus gesture.
12073 * - It pilfers pointers and then configures itself to no longer be a spy.
12074 * - The stylus interceptor continues to receive the rest of the gesture.
12075 */
12076TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
12077 auto [overlay, window] = setupStylusOverlayScenario();
12078 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012079 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000012080
12081 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
12082 overlay->consumeMotionDown();
12083 window->consumeMotionDown();
12084
12085 // The interceptor pilfers the pointers.
12086 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
12087 window->consumeMotionCancel();
12088
12089 // The interceptor configures itself so that it is no longer a spy.
12090 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012091 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000012092
12093 // It continues to receive the rest of the stylus gesture.
12094 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
12095 overlay->consumeMotionMove();
12096 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
12097 overlay->consumeMotionUp();
12098
12099 window->assertNoEvents();
12100}
12101
Prabir Pradhan5735a322022-04-11 17:23:34 +000012102struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012103 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000012104 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000012105 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
12106 std::unique_ptr<InputDispatcher>& mDispatcher;
12107
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012108 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000012109 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
12110
12111 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012112 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000012113 ADISPLAY_ID_DEFAULT, {100, 200},
12114 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
12115 AMOTION_EVENT_INVALID_CURSOR_POSITION},
12116 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
12117 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
12118 }
12119
12120 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012121 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000012122 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000012123 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000012124 mPolicyFlags);
12125 }
12126
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012127 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000012128 std::shared_ptr<FakeApplicationHandle> overlayApplication =
12129 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012130 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
12131 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000012132 window->setOwnerInfo(mPid, mUid);
12133 return window;
12134 }
12135};
12136
12137using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
12138
12139TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012140 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012141 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012142 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012143
12144 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12145 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12146 window->consumeMotionDown();
12147
12148 setFocusedWindow(window);
12149 window->consumeFocusEvent(true);
12150
12151 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12152 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
12153 window->consumeKeyDown(ADISPLAY_ID_NONE);
12154}
12155
12156TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012157 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012158 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012159 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012160
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012161 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012162 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
12163 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12164
12165 setFocusedWindow(window);
12166 window->consumeFocusEvent(true);
12167
12168 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
12169 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
12170 window->assertNoEvents();
12171}
12172
12173TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012174 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012175 auto window = owner.createWindow("Owned window");
12176 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012177 spy->setSpy(true);
12178 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012179 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012180
12181 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12182 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12183 spy->consumeMotionDown();
12184 window->consumeMotionDown();
12185}
12186
12187TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012188 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012189 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012190
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012191 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012192 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012193 randosSpy->setSpy(true);
12194 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012195 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012196
12197 // The event is targeted at owner's window, so injection should succeed, but the spy should
12198 // not receive the event.
12199 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12200 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12201 randosSpy->assertNoEvents();
12202 window->consumeMotionDown();
12203}
12204
12205TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012206 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012207 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012208
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012209 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012210 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012211 randosSpy->setSpy(true);
12212 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012213 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012214
12215 // A user that has injection permission can inject into any window.
12216 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012217 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000012218 ADISPLAY_ID_DEFAULT));
12219 randosSpy->consumeMotionDown();
12220 window->consumeMotionDown();
12221
12222 setFocusedWindow(randosSpy);
12223 randosSpy->consumeFocusEvent(true);
12224
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012225 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000012226 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
12227 window->assertNoEvents();
12228}
12229
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012230TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012231 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012232 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012233
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012234 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012235 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012236 randosWindow->setFrame(Rect{-10, -10, -5, -5});
12237 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012238 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012239
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012240 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000012241 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12242 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12243 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012244 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000012245}
12246
Prabir Pradhan64f21d22023-11-28 21:19:42 +000012247using InputDispatcherPointerInWindowTest = InputDispatcherTest;
12248
12249TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
12250 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12251
12252 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12253 ADISPLAY_ID_DEFAULT);
12254 left->setFrame(Rect(0, 0, 100, 100));
12255 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12256 "Right Window", ADISPLAY_ID_DEFAULT);
12257 right->setFrame(Rect(100, 0, 200, 100));
12258 sp<FakeWindowHandle> spy =
12259 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
12260 spy->setFrame(Rect(0, 0, 200, 100));
12261 spy->setTrustedOverlay(true);
12262 spy->setSpy(true);
12263
12264 mDispatcher->onWindowInfosChanged(
12265 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
12266
12267 // Hover into the left window.
12268 mDispatcher->notifyMotion(
12269 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
12270 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
12271 .build());
12272
12273 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12274 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12275
12276 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12277 /*pointerId=*/0));
12278 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12279 /*pointerId=*/0));
12280 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12281 /*pointerId=*/0));
12282
12283 // Hover move to the right window.
12284 mDispatcher->notifyMotion(
12285 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
12286 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
12287 .build());
12288
12289 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12290 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12291 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
12292
12293 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12294 /*pointerId=*/0));
12295 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12296 /*pointerId=*/0));
12297 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12298 /*pointerId=*/0));
12299
12300 // Stop hovering.
12301 mDispatcher->notifyMotion(
12302 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
12303 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
12304 .build());
12305
12306 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12307 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12308
12309 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12310 /*pointerId=*/0));
12311 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12312 /*pointerId=*/0));
12313 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12314 /*pointerId=*/0));
12315}
12316
12317TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
12318 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12319
12320 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12321 ADISPLAY_ID_DEFAULT);
12322 left->setFrame(Rect(0, 0, 100, 100));
12323 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12324 "Right Window", ADISPLAY_ID_DEFAULT);
12325 right->setFrame(Rect(100, 0, 200, 100));
12326 sp<FakeWindowHandle> spy =
12327 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
12328 spy->setFrame(Rect(0, 0, 200, 100));
12329 spy->setTrustedOverlay(true);
12330 spy->setSpy(true);
12331
12332 mDispatcher->onWindowInfosChanged(
12333 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
12334
12335 // First pointer down on left window.
12336 mDispatcher->notifyMotion(
12337 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12338 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12339 .build());
12340
12341 left->consumeMotionDown();
12342 spy->consumeMotionDown();
12343
12344 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12345 /*pointerId=*/0));
12346 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12347 /*pointerId=*/0));
12348 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12349 /*pointerId=*/0));
12350
12351 // Second pointer down on right window.
12352 mDispatcher->notifyMotion(
12353 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12354 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12355 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
12356 .build());
12357
12358 left->consumeMotionMove();
12359 right->consumeMotionDown();
12360 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
12361
12362 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12363 /*pointerId=*/0));
12364 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12365 /*pointerId=*/0));
12366 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12367 /*pointerId=*/0));
12368 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12369 /*pointerId=*/1));
12370 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12371 /*pointerId=*/1));
12372 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12373 /*pointerId=*/1));
12374
12375 // Second pointer up.
12376 mDispatcher->notifyMotion(
12377 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
12378 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12379 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
12380 .build());
12381
12382 left->consumeMotionMove();
12383 right->consumeMotionUp();
12384 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
12385
12386 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12387 /*pointerId=*/0));
12388 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12389 /*pointerId=*/0));
12390 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12391 /*pointerId=*/0));
12392 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12393 /*pointerId=*/1));
12394 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12395 /*pointerId=*/1));
12396 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12397 /*pointerId=*/1));
12398
12399 // First pointer up.
12400 mDispatcher->notifyMotion(
12401 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
12402 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12403 .build());
12404
12405 left->consumeMotionUp();
12406 spy->consumeMotionUp();
12407
12408 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12409 /*pointerId=*/0));
12410 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12411 /*pointerId=*/0));
12412 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12413 /*pointerId=*/0));
12414}
12415
12416TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
12417 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12418
12419 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12420 ADISPLAY_ID_DEFAULT);
12421 left->setFrame(Rect(0, 0, 100, 100));
12422 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12423 "Right Window", ADISPLAY_ID_DEFAULT);
12424 right->setFrame(Rect(100, 0, 200, 100));
12425
12426 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
12427
12428 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12429 /*pointerId=*/0));
12430 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12431 /*pointerId=*/0));
12432
12433 // Hover move into the window.
12434 mDispatcher->notifyMotion(
12435 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12436 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
12437 .rawXCursorPosition(50)
12438 .rawYCursorPosition(50)
12439 .deviceId(DEVICE_ID)
12440 .build());
12441
12442 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12443
12444 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12445 /*pointerId=*/0));
12446
12447 // Move the mouse with another device. This cancels the hovering pointer from the first device.
12448 mDispatcher->notifyMotion(
12449 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12450 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
12451 .rawXCursorPosition(51)
12452 .rawYCursorPosition(50)
12453 .deviceId(SECOND_DEVICE_ID)
12454 .build());
12455
12456 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12457 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12458
12459 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
12460 // a HOVER_EXIT from the first device.
12461 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12462 /*pointerId=*/0));
12463 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
12464 SECOND_DEVICE_ID,
12465 /*pointerId=*/0));
12466
12467 // Move the mouse outside the window. Document the current behavior, where the window does not
12468 // receive HOVER_EXIT even though the mouse left the window.
12469 mDispatcher->notifyMotion(
12470 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12471 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
12472 .rawXCursorPosition(150)
12473 .rawYCursorPosition(50)
12474 .deviceId(SECOND_DEVICE_ID)
12475 .build());
12476
12477 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12478 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12479 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12480 /*pointerId=*/0));
12481 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
12482 SECOND_DEVICE_ID,
12483 /*pointerId=*/0));
12484}
12485
Garfield Tane84e6f92019-08-29 17:28:41 -070012486} // namespace android::inputdispatcher