blob: 93949954ccc1e0b7db75fd1cffd2fde4d0a8642b [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 Pradhane3b28dd2023-10-06 04:19:29 +000020#include "TestEventMatchers.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080021
Cody Heiner166a5af2023-07-07 12:25:00 -070022#include <NotifyArgsBuilders.h>
Prabir Pradhan5893d362023-11-17 04:30:40 +000023#include <android-base/logging.h>
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070024#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080025#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080026#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070027#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070028#include <binder/Binder.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000029#include <com_android_input_flags.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000030#include <fcntl.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000031#include <flag_macros.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080032#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080033#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100034#include <input/Input.h>
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070035#include <input/PrintTools.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080036#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080037#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100038
Garfield Tan1c7bc862020-01-28 13:24:04 -080039#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080040#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070041#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080042#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080043#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080044
Garfield Tan1c7bc862020-01-28 13:24:04 -080045using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050046using android::gui::FocusRequest;
47using android::gui::TouchOcclusionMode;
48using android::gui::WindowInfo;
49using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080050using android::os::InputEventInjectionResult;
51using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080052
Garfield Tane84e6f92019-08-29 17:28:41 -070053namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080054
Dominik Laskowski2f01d772022-03-23 16:01:29 -070055using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080056using testing::AllOf;
Prabir Pradhan5893d362023-11-17 04:30:40 +000057using testing::Not;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070058
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070059namespace {
60
Michael Wrightd02c5b62014-02-10 15:10:22 -080061// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000062static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080063
64// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000065static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080066static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080067
Jeff Brownf086ddb2014-02-11 14:28:48 -080068// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000069static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
70static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080071
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000072// Ensure common actions are interchangeable between keys and motions for convenience.
73static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
74static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080075static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
76static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
77static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
78static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070079static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080080static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070081static constexpr int32_t ACTION_SCROLL = AMOTION_EVENT_ACTION_SCROLL;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080082static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080083static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080084/**
85 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
86 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
87 * index 0) is the new pointer going down. The same pointer could have been placed at a different
88 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
89 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
90 * pointer id=0 leaves but the pointer id=1 remains.
91 */
92static constexpr int32_t POINTER_0_DOWN =
93 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080094static constexpr int32_t POINTER_1_DOWN =
95 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000096static constexpr int32_t POINTER_2_DOWN =
97 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000098static constexpr int32_t POINTER_3_DOWN =
99 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +0000100static constexpr int32_t POINTER_0_UP =
101 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800102static constexpr int32_t POINTER_1_UP =
103 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +0000104static constexpr int32_t POINTER_2_UP =
105 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800106
Antonio Kantek15beb512022-06-13 22:35:41 +0000107// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000108static constexpr gui::Pid WINDOW_PID{999};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000109static constexpr gui::Uid WINDOW_UID{1001};
Prabir Pradhan5735a322022-04-11 17:23:34 +0000110
Antonio Kantek15beb512022-06-13 22:35:41 +0000111// The default pid and uid for the windows created on the secondary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000112static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000113static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000114
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000115// An arbitrary pid of the gesture monitor window
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000116static constexpr gui::Pid MONITOR_PID{2001};
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000117
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700118/**
119 * If we expect to receive the event, the timeout can be made very long. When the test are running
120 * correctly, we will actually never wait until the end of the timeout because the wait will end
121 * when the event comes in. Still, this value shouldn't be infinite. During development, a local
122 * change may cause the test to fail. This timeout should be short enough to not annoy so that the
123 * developer can see the failure quickly (on human scale).
124 */
125static constexpr std::chrono::duration CONSUME_TIMEOUT_EVENT_EXPECTED = 1000ms;
126/**
127 * When no event is expected, we can have a very short timeout. A large value here would slow down
128 * the tests. In the unlikely event of system being too slow, the event may still be present but the
129 * timeout would complete before it is consumed. This would result in test flakiness. If this
130 * occurs, the flakiness rate would be high. Since the flakes are treated with high priority, this
131 * would get noticed and addressed quickly.
132 */
133static constexpr std::chrono::duration CONSUME_TIMEOUT_NO_EVENT_EXPECTED = 10ms;
134
Arthur Hungc539dbb2022-12-08 07:45:36 +0000135static constexpr int expectedWallpaperFlags =
136 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
137
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800138using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
139
Gang Wang342c9272020-01-13 13:15:04 -0500140/**
141 * Return a DOWN key event with KEYCODE_A.
142 */
143static KeyEvent getTestKeyEvent() {
144 KeyEvent event;
145
Garfield Tanfbe732e2020-01-24 11:26:14 -0800146 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
147 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
148 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500149 return event;
150}
151
Michael Wrightd02c5b62014-02-10 15:10:22 -0800152// --- FakeInputDispatcherPolicy ---
153
154class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000155 struct AnrResult {
156 sp<IBinder> token{};
157 gui::Pid pid{gui::Pid::INVALID};
158 };
Prabir Pradhanedd96402022-02-15 01:46:16 -0800159
Michael Wrightd02c5b62014-02-10 15:10:22 -0800160public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000161 FakeInputDispatcherPolicy() = default;
162 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800163
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800164 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700165 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700166 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700167 EXPECT_EQ(event.getDisplayId(), args.displayId);
168
169 const auto& keyEvent = static_cast<const KeyEvent&>(event);
170 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
171 EXPECT_EQ(keyEvent.getAction(), args.action);
172 });
Jackal Guof9696682018-10-05 12:23:23 +0800173 }
174
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700175 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
176 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700177 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700178 EXPECT_EQ(event.getDisplayId(), args.displayId);
179
180 const auto& motionEvent = static_cast<const MotionEvent&>(event);
181 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
182 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000183 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
184 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
185 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
186 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700187 });
Jackal Guof9696682018-10-05 12:23:23 +0800188 }
189
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700190 void assertFilterInputEventWasNotCalled() {
191 std::scoped_lock lock(mLock);
192 ASSERT_EQ(nullptr, mFilteredEvent);
193 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800194
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800195 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700196 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800197 ASSERT_TRUE(mConfigurationChangedTime)
198 << "Timed out waiting for configuration changed call";
199 ASSERT_EQ(*mConfigurationChangedTime, when);
200 mConfigurationChangedTime = std::nullopt;
201 }
202
203 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700204 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800205 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800206 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800207 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
208 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
209 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
210 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
211 mLastNotifySwitch = std::nullopt;
212 }
213
chaviwfd6d3512019-03-25 13:23:49 -0700214 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700215 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800216 ASSERT_EQ(touchedToken, mOnPointerDownToken);
217 mOnPointerDownToken.clear();
218 }
219
220 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700221 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800222 ASSERT_TRUE(mOnPointerDownToken == nullptr)
223 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700224 }
225
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700226 // This function must be called soon after the expected ANR timer starts,
227 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500228 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700229 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500230 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800231 std::unique_lock lock(mLock);
232 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500233 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800234 ASSERT_NO_FATAL_FAILURE(
235 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500236 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700237 }
238
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000239 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800240 const sp<WindowInfoHandle>& window) {
241 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
242 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
243 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500244 }
245
Prabir Pradhanedd96402022-02-15 01:46:16 -0800246 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
247 const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000248 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800249 std::unique_lock lock(mLock);
250 android::base::ScopedLockAssertion assumeLocked(mLock);
251 AnrResult result;
252 ASSERT_NO_FATAL_FAILURE(result =
253 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000254 ASSERT_EQ(expectedToken, result.token);
255 ASSERT_EQ(expectedPid, result.pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500256 }
257
Prabir Pradhanedd96402022-02-15 01:46:16 -0800258 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000259 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500260 std::unique_lock lock(mLock);
261 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800262 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
263 const auto& [token, _] = result;
264 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000265 }
266
Prabir Pradhanedd96402022-02-15 01:46:16 -0800267 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000268 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800269 std::unique_lock lock(mLock);
270 android::base::ScopedLockAssertion assumeLocked(mLock);
271 AnrResult result;
272 ASSERT_NO_FATAL_FAILURE(
273 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000274 ASSERT_EQ(expectedToken, result.token);
275 ASSERT_EQ(expectedPid, result.pid);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800276 }
277
278 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000279 sp<IBinder> getResponsiveWindowToken() {
280 std::unique_lock lock(mLock);
281 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800282 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
283 const auto& [token, _] = result;
284 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700285 }
286
287 void assertNotifyAnrWasNotCalled() {
288 std::scoped_lock lock(mLock);
289 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800290 ASSERT_TRUE(mAnrWindows.empty());
291 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500292 << "ANR was not called, but please also consume the 'connection is responsive' "
293 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700294 }
295
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000296 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800297 std::unique_lock lock(mLock);
298 base::ScopedLockAssertion assumeLocked(mLock);
299
300 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
301 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000302 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800303 enabled;
304 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000305 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
306 << ") to be called.";
307 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800308 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000309 auto request = *mPointerCaptureRequest;
310 mPointerCaptureRequest.reset();
311 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800312 }
313
314 void assertSetPointerCaptureNotCalled() {
315 std::unique_lock lock(mLock);
316 base::ScopedLockAssertion assumeLocked(mLock);
317
318 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000319 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800320 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000321 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800322 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000323 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800324 }
325
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -0700326 void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
327 const sp<IBinder>& targetToken) {
328 dispatcher.waitForIdle();
arthurhungf452d0b2021-01-06 00:19:52 +0800329 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800330 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800331 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800332 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800333 }
334
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800335 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
336 std::unique_lock lock(mLock);
337 base::ScopedLockAssertion assumeLocked(mLock);
338 std::optional<sp<IBinder>> receivedToken =
339 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
340 mNotifyInputChannelBroken);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000341 ASSERT_TRUE(receivedToken.has_value()) << "Did not receive the broken channel token";
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800342 ASSERT_EQ(token, *receivedToken);
343 }
344
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800345 /**
346 * Set policy timeout. A value of zero means next key will not be intercepted.
347 */
348 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
349 mInterceptKeyTimeout = timeout;
350 }
351
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700352 void setStaleEventTimeout(std::chrono::nanoseconds timeout) { mStaleEventTimeout = timeout; }
353
Josep del Riob3981622023-04-18 15:49:45 +0000354 void assertUserActivityPoked() {
355 std::scoped_lock lock(mLock);
356 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
357 }
358
359 void assertUserActivityNotPoked() {
360 std::scoped_lock lock(mLock);
361 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
362 }
363
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000364 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000365 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
366 }
367
368 void assertNotifyDeviceInteractionWasNotCalled() {
369 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
370 }
371
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000372 void setUnhandledKeyHandler(std::function<std::optional<KeyEvent>(const KeyEvent&)> handler) {
373 std::scoped_lock lock(mLock);
374 mUnhandledKeyHandler = handler;
375 }
376
377 void assertUnhandledKeyReported(int32_t keycode) {
378 std::unique_lock lock(mLock);
379 base::ScopedLockAssertion assumeLocked(mLock);
380 std::optional<int32_t> unhandledKeycode =
381 getItemFromStorageLockedInterruptible(100ms, mReportedUnhandledKeycodes, lock,
382 mNotifyUnhandledKey);
383 ASSERT_TRUE(unhandledKeycode) << "Expected unhandled key to be reported";
384 ASSERT_EQ(unhandledKeycode, keycode);
385 }
386
387 void assertUnhandledKeyNotReported() {
388 std::unique_lock lock(mLock);
389 base::ScopedLockAssertion assumeLocked(mLock);
390 std::optional<int32_t> unhandledKeycode =
391 getItemFromStorageLockedInterruptible(10ms, mReportedUnhandledKeycodes, lock,
392 mNotifyUnhandledKey);
393 ASSERT_FALSE(unhandledKeycode) << "Expected unhandled key NOT to be reported";
394 }
395
Michael Wrightd02c5b62014-02-10 15:10:22 -0800396private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700397 std::mutex mLock;
398 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
399 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
400 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
401 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800402
Prabir Pradhan99987712020-11-10 18:43:05 -0800403 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000404
405 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800406
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700407 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700408 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800409 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
410 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700411 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800412 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
413 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700414
arthurhungf452d0b2021-01-06 00:19:52 +0800415 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800416 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000417 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800418
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800419 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
420
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700421 std::chrono::nanoseconds mStaleEventTimeout = 1000ms;
422
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000423 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000424
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000425 std::condition_variable mNotifyUnhandledKey;
426 std::queue<int32_t> mReportedUnhandledKeycodes GUARDED_BY(mLock);
427 std::function<std::optional<KeyEvent>(const KeyEvent&)> mUnhandledKeyHandler GUARDED_BY(mLock);
428
Prabir Pradhanedd96402022-02-15 01:46:16 -0800429 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
430 // for a specific container to become non-empty. When the container is non-empty, return the
431 // first entry from the container and erase it.
432 template <class T>
433 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
434 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
435 // If there is an ANR, Dispatcher won't be idle because there are still events
436 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
437 // before checking if ANR was called.
438 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
439 // to provide it some time to act. 100ms seems reasonable.
440 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
441 const std::chrono::time_point start = std::chrono::steady_clock::now();
442 std::optional<T> token =
443 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
444 if (!token.has_value()) {
445 ADD_FAILURE() << "Did not receive the ANR callback";
446 return {};
447 }
448
449 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
450 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
451 // the dispatcher started counting before this function was called
452 if (std::chrono::abs(timeout - waited) > 100ms) {
453 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
454 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
455 << "ms, but waited "
456 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
457 << "ms instead";
458 }
459 return *token;
460 }
461
462 template <class T>
463 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
464 std::queue<T>& storage,
465 std::unique_lock<std::mutex>& lock,
466 std::condition_variable& condition)
467 REQUIRES(mLock) {
468 condition.wait_for(lock, timeout,
469 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
470 if (storage.empty()) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800471 return std::nullopt;
472 }
473 T item = storage.front();
474 storage.pop();
475 return std::make_optional(item);
476 }
477
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600478 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700479 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800480 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800481 }
482
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000483 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800484 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700485 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800486 ASSERT_TRUE(pid.has_value());
487 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700488 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500489 }
490
Prabir Pradhanedd96402022-02-15 01:46:16 -0800491 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000492 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500493 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800494 ASSERT_TRUE(pid.has_value());
495 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500496 mNotifyAnr.notify_all();
497 }
498
499 void notifyNoFocusedWindowAnr(
500 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
501 std::scoped_lock lock(mLock);
502 mAnrApplications.push(applicationHandle);
503 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800504 }
505
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800506 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
507 std::scoped_lock lock(mLock);
508 mBrokenInputChannels.push(connectionToken);
509 mNotifyInputChannelBroken.notify_all();
510 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800511
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600512 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700513
Chris Yef59a2f42020-10-16 12:55:26 -0700514 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
515 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
516 const std::vector<float>& values) override {}
517
518 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
519 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000520
Chris Yefb552902021-02-03 17:18:37 -0800521 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
522
Prabir Pradhana41d2442023-04-20 21:30:40 +0000523 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700524 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000525 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700526 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000527 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
528 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800529 break;
530 }
531
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700532 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000533 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
534 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800535 break;
536 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700537 default: {
538 ADD_FAILURE() << "Should only filter keys or motions";
539 break;
540 }
Jackal Guof9696682018-10-05 12:23:23 +0800541 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800542 return true;
543 }
544
Prabir Pradhana41d2442023-04-20 21:30:40 +0000545 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
546 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800547 // Clear intercept state when we handled the event.
548 mInterceptKeyTimeout = 0ms;
549 }
550 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800551
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600552 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800553
Prabir Pradhana41d2442023-04-20 21:30:40 +0000554 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800555 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
556 // Clear intercept state so we could dispatch the event in next wake.
557 mInterceptKeyTimeout = 0ms;
558 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800559 }
560
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000561 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent& event,
Prabir Pradhana41d2442023-04-20 21:30:40 +0000562 uint32_t) override {
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000563 std::scoped_lock lock(mLock);
564 mReportedUnhandledKeycodes.emplace(event.getKeyCode());
565 mNotifyUnhandledKey.notify_all();
566 return mUnhandledKeyHandler != nullptr ? mUnhandledKeyHandler(event) : std::nullopt;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800567 }
568
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600569 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
570 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700571 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800572 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
573 * essentially a passthrough for notifySwitch.
574 */
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000575 mLastNotifySwitch =
576 NotifySwitchArgs(InputEvent::nextId(), when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800577 }
578
Josep del Riob3981622023-04-18 15:49:45 +0000579 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
580 std::scoped_lock lock(mLock);
581 mPokedUserActivity = true;
582 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800583
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700584 bool isStaleEvent(nsecs_t currentTime, nsecs_t eventTime) override {
585 return std::chrono::nanoseconds(currentTime - eventTime) >= mStaleEventTimeout;
586 }
587
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600588 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700589 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700590 mOnPointerDownToken = newToken;
591 }
592
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000593 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800594 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000595 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800596 mPointerCaptureChangedCondition.notify_all();
597 }
598
arthurhungf452d0b2021-01-06 00:19:52 +0800599 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
600 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800601 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800602 mDropTargetWindowToken = token;
603 }
604
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000605 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000606 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000607 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
608 }
609
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700610 void assertFilterInputEventWasCalledInternal(
611 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700612 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800613 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700614 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800615 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800616 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800617};
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700618} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800619
Michael Wrightd02c5b62014-02-10 15:10:22 -0800620// --- InputDispatcherTest ---
621
622class InputDispatcherTest : public testing::Test {
623protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000624 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700625 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800626
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000627 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000628 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700629 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
630
Harry Cutts101ee9b2023-07-06 18:04:14 +0000631 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000632 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700633 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800634 }
635
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000636 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700637 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000638 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700639 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800640 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700641
642 /**
643 * Used for debugging when writing the test
644 */
645 void dumpDispatcherState() {
646 std::string dump;
647 mDispatcher->dump(dump);
648 std::stringstream ss(dump);
649 std::string to;
650
651 while (std::getline(ss, to, '\n')) {
652 ALOGE("%s", to.c_str());
653 }
654 }
Vishnu Nair958da932020-08-21 17:12:37 -0700655
Chavi Weingarten847e8512023-03-29 00:26:09 +0000656 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700657 FocusRequest request;
658 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000659 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700660 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
661 request.displayId = window->getInfo()->displayId;
662 mDispatcher->setFocusedWindow(request);
663 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800664};
665
Michael Wrightd02c5b62014-02-10 15:10:22 -0800666TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
667 KeyEvent event;
668
669 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800670 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
671 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000672 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600673 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800674 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000675 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000676 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800677 << "Should reject key events with undefined action.";
678
679 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800680 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
681 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600682 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800683 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000684 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000685 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800686 << "Should reject key events with ACTION_MULTIPLE.";
687}
688
689TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
690 MotionEvent event;
691 PointerProperties pointerProperties[MAX_POINTERS + 1];
692 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800693 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800694 pointerProperties[i].clear();
695 pointerProperties[i].id = i;
696 pointerCoords[i].clear();
697 }
698
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800699 // Some constants commonly used below
700 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
701 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
702 constexpr int32_t metaState = AMETA_NONE;
703 constexpr MotionClassification classification = MotionClassification::NONE;
704
chaviw9eaa22c2020-07-01 16:21:27 -0700705 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800706 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800707 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000708 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700709 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700710 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
711 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000712 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800713 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000714 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000715 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800716 << "Should reject motion events with undefined action.";
717
718 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800719 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800720 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
721 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
722 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
723 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000724 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800725 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000726 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000727 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800728 << "Should reject motion events with pointer down index too large.";
729
Garfield Tanfbe732e2020-01-24 11:26:14 -0800730 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700731 AMOTION_EVENT_ACTION_POINTER_DOWN |
732 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700733 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
734 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700735 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000736 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800737 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000738 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000739 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800740 << "Should reject motion events with pointer down index too small.";
741
742 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800743 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800744 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
745 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
746 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
747 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000748 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800749 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000750 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000751 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800752 << "Should reject motion events with pointer up index too large.";
753
Garfield Tanfbe732e2020-01-24 11:26:14 -0800754 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700755 AMOTION_EVENT_ACTION_POINTER_UP |
756 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700757 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
758 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700759 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000760 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800761 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000762 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000763 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800764 << "Should reject motion events with pointer up index too small.";
765
766 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800767 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
768 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700769 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700770 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
771 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000772 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800773 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000774 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000775 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800776 << "Should reject motion events with 0 pointers.";
777
Garfield Tanfbe732e2020-01-24 11:26:14 -0800778 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
779 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700780 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700781 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
782 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000783 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800784 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000785 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000786 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800787 << "Should reject motion events with more than MAX_POINTERS pointers.";
788
789 // Rejects motion events with invalid pointer ids.
790 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800791 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
792 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700793 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700794 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
795 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000796 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800797 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000798 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000799 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800800 << "Should reject motion events with pointer ids less than 0.";
801
802 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800803 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
804 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700805 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700806 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
807 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000808 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800809 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000810 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000811 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800812 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
813
814 // Rejects motion events with duplicate pointer ids.
815 pointerProperties[0].id = 1;
816 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800817 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
818 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700819 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700820 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
821 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000822 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800823 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000824 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000825 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800826 << "Should reject motion events with duplicate pointer ids.";
827}
828
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800829/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
830
831TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
832 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000833 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800834 ASSERT_TRUE(mDispatcher->waitForIdle());
835
836 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
837}
838
839TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000840 NotifySwitchArgs args(InputEvent::nextId(), /*eventTime=*/20, /*policyFlags=*/0,
841 /*switchValues=*/1,
Harry Cutts33476232023-01-30 19:57:29 +0000842 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000843 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800844
845 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
846 args.policyFlags |= POLICY_FLAG_TRUSTED;
847 mFakePolicy->assertNotifySwitchWasCalled(args);
848}
849
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700850namespace {
851
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700852static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700853// Default input dispatching timeout if there is no focused application or paused window
854// from which to determine an appropriate dispatching timeout.
855static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
856 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
857 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800858
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800859class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800860public:
Garfield Tan15601662020-09-22 15:32:38 -0700861 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700862 : mConsumer(std::move(clientChannel)), mName(name) {}
chaviwd1c23182019-12-20 18:44:56 -0800863
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000864 InputEvent* consume(std::chrono::milliseconds timeout, bool handled = false) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700865 InputEvent* event;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700866 std::optional<uint32_t> consumeSeq = receiveEvent(timeout, &event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700867 if (!consumeSeq) {
868 return nullptr;
869 }
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000870 finishEvent(*consumeSeq, handled);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700871 return event;
872 }
873
874 /**
875 * Receive an event without acknowledging it.
876 * Return the sequence number that could later be used to send finished signal.
877 */
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700878 std::optional<uint32_t> receiveEvent(std::chrono::milliseconds timeout,
879 InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800880 uint32_t consumeSeq;
881 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800882
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800883 std::chrono::time_point start = std::chrono::steady_clock::now();
884 status_t status = WOULD_BLOCK;
885 while (status == WOULD_BLOCK) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700886 status = mConsumer.consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
887 &event);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800888 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700889 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800890 break;
891 }
892 }
893
894 if (status == WOULD_BLOCK) {
895 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700896 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800897 }
898
899 if (status != OK) {
900 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700901 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800902 }
903 if (event == nullptr) {
904 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700905 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800906 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700907 if (outEvent != nullptr) {
908 *outEvent = event;
909 }
910 return consumeSeq;
911 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800912
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700913 /**
914 * To be used together with "receiveEvent" to complete the consumption of an event.
915 */
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000916 void finishEvent(uint32_t consumeSeq, bool handled = true) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700917 const status_t status = mConsumer.sendFinishedSignal(consumeSeq, handled);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700918 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800919 }
920
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000921 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700922 const status_t status = mConsumer.sendTimeline(inputEventId, timeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000923 ASSERT_EQ(OK, status);
924 }
925
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700926 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000927 std::optional<int32_t> expectedDisplayId,
928 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700929 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800930
931 ASSERT_NE(nullptr, event) << mName.c_str()
932 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800933 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700934 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
935 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800936
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000937 if (expectedDisplayId.has_value()) {
938 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
939 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800940
Tiger Huang8664f8c2018-10-11 19:14:35 +0800941 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700942 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800943 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700944 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000945 if (expectedFlags.has_value()) {
946 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
947 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800948 break;
949 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700950 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800951 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700952 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000953 if (expectedFlags.has_value()) {
954 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
955 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800956 break;
957 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700958 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100959 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
960 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700961 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800962 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
963 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700964 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000965 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
966 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700967 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800968 FAIL() << "Use 'consumeDragEvent' for DRAG events";
969 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800970 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800971 }
972
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800973 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700974 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800975
976 if (event == nullptr) {
977 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
978 return nullptr;
979 }
980
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700981 if (event->getType() != InputEventType::MOTION) {
982 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800983 return nullptr;
984 }
985 return static_cast<MotionEvent*>(event);
986 }
987
988 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
989 MotionEvent* motionEvent = consumeMotion();
990 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
991 ASSERT_THAT(*motionEvent, matcher);
992 }
993
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100994 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700995 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100996 ASSERT_NE(nullptr, event) << mName.c_str()
997 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700998 ASSERT_EQ(InputEventType::FOCUS, event->getType())
999 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001000
1001 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1002 << mName.c_str() << ": event displayId should always be NONE.";
1003
1004 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1005 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001006 }
1007
Prabir Pradhan99987712020-11-10 18:43:05 -08001008 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001009 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -08001010 ASSERT_NE(nullptr, event) << mName.c_str()
1011 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001012 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1013 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001014
1015 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1016 << mName.c_str() << ": event displayId should always be NONE.";
1017
1018 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1019 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1020 }
1021
arthurhungb89ccb02020-12-30 16:19:01 +08001022 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001023 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +08001024 ASSERT_NE(nullptr, event) << mName.c_str()
1025 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001026 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001027
1028 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1029 << mName.c_str() << ": event displayId should always be NONE.";
1030
1031 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1032 EXPECT_EQ(isExiting, dragEvent.isExiting());
1033 EXPECT_EQ(x, dragEvent.getX());
1034 EXPECT_EQ(y, dragEvent.getY());
1035 }
1036
Antonio Kantekf16f2832021-09-28 04:39:20 +00001037 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001038 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +00001039 ASSERT_NE(nullptr, event) << mName.c_str()
1040 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001041 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1042 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001043
1044 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1045 << mName.c_str() << ": event displayId should always be NONE.";
1046 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1047 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1048 }
1049
chaviwd1c23182019-12-20 18:44:56 -08001050 void assertNoEvents() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001051 InputEvent* event = consume(CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001052 if (event == nullptr) {
1053 return;
1054 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001055 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001056 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001057 ADD_FAILURE() << "Received key event " << keyEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001058 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001059 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001060 ADD_FAILURE() << "Received motion event " << motionEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001061 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001062 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1063 ADD_FAILURE() << "Received focus event, hasFocus = "
1064 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001065 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001066 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1067 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1068 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001069 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001070 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1071 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1072 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001073 }
1074 FAIL() << mName.c_str()
1075 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001076 }
1077
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001078 sp<IBinder> getToken() { return mConsumer.getChannel()->getConnectionToken(); }
chaviwd1c23182019-12-20 18:44:56 -08001079
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001080 int getChannelFd() { return mConsumer.getChannel()->getFd().get(); }
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001081
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001082private:
1083 InputConsumer mConsumer;
chaviwd1c23182019-12-20 18:44:56 -08001084 PreallocatedInputEventFactory mEventFactory;
1085
1086 std::string mName;
1087};
1088
chaviw3277faf2021-05-19 16:45:23 -05001089class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001090public:
1091 static const int32_t WIDTH = 600;
1092 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001093
Chris Yea209fde2020-07-22 13:54:51 -07001094 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001095 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001096 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001097 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001098 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001099 base::Result<std::unique_ptr<InputChannel>> channel =
1100 dispatcher->createInputChannel(name);
1101 token = (*channel)->getConnectionToken();
1102 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001103 }
1104
1105 inputApplicationHandle->updateInfo();
1106 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1107
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001108 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001109 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001110 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001111 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001112 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001113 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001114 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001115 mInfo.globalScaleFactor = 1.0;
1116 mInfo.touchableRegion.clear();
1117 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001118 mInfo.ownerPid = WINDOW_PID;
1119 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001120 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001121 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001122 }
1123
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001124 sp<FakeWindowHandle> clone(int32_t displayId) {
1125 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1126 handle->mInfo = mInfo;
1127 handle->mInfo.displayId = displayId;
1128 handle->mInfo.id = sId++;
1129 handle->mInputReceiver = mInputReceiver;
1130 return handle;
1131 }
1132
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001133 void setTouchable(bool touchable) {
1134 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1135 }
chaviwd1c23182019-12-20 18:44:56 -08001136
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001137 void setFocusable(bool focusable) {
1138 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1139 }
1140
1141 void setVisible(bool visible) {
1142 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1143 }
Vishnu Nair958da932020-08-21 17:12:37 -07001144
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001145 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001146 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001147 }
1148
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001149 void setPaused(bool paused) {
1150 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1151 }
1152
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001153 void setPreventSplitting(bool preventSplitting) {
1154 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001155 }
1156
1157 void setSlippery(bool slippery) {
1158 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1159 }
1160
1161 void setWatchOutsideTouch(bool watchOutside) {
1162 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1163 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001164
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001165 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1166
1167 void setInterceptsStylus(bool interceptsStylus) {
1168 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1169 }
1170
1171 void setDropInput(bool dropInput) {
1172 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1173 }
1174
1175 void setDropInputIfObscured(bool dropInputIfObscured) {
1176 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1177 }
1178
1179 void setNoInputChannel(bool noInputChannel) {
1180 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1181 }
1182
Josep del Riob3981622023-04-18 15:49:45 +00001183 void setDisableUserActivity(bool disableUserActivity) {
1184 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1185 }
1186
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001187 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1188
chaviw3277faf2021-05-19 16:45:23 -05001189 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001190
Bernardo Rufino7393d172021-02-26 13:56:11 +00001191 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1192
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001193 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001194 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001195 mInfo.touchableRegion.clear();
1196 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001197
1198 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1199 ui::Transform translate;
1200 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1201 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001202 }
1203
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001204 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1205
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001206 void setIsWallpaper(bool isWallpaper) {
1207 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1208 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001209
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001210 void setDupTouchToWallpaper(bool hasWallpaper) {
1211 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1212 }
chaviwd1c23182019-12-20 18:44:56 -08001213
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001214 void setTrustedOverlay(bool trustedOverlay) {
1215 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1216 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001217
chaviw9eaa22c2020-07-01 16:21:27 -07001218 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1219 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1220 }
1221
1222 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001223
yunho.shinf4a80b82020-11-16 21:13:57 +09001224 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1225
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001226 const KeyEvent& consumeKey(bool handled = true) {
1227 const InputEvent& event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED, handled);
1228 if (event.getType() != InputEventType::KEY) {
1229 LOG(FATAL) << "Instead of key event, got " << event;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001230 }
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001231 return static_cast<const KeyEvent&>(event);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001232 }
1233
1234 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001235 const KeyEvent& keyEvent = consumeKey();
1236 ASSERT_THAT(keyEvent, matcher);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001237 }
1238
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001239 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001240 consumeKeyEvent(AllOf(WithKeyAction(ACTION_DOWN), WithDisplayId(expectedDisplayId),
1241 WithFlags(expectedFlags)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001242 }
1243
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001244 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001245 consumeKeyEvent(AllOf(WithKeyAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1246 WithFlags(expectedFlags)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001247 }
1248
Svet Ganov5d3bc372020-01-26 23:11:07 -08001249 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001250 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001251 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1252 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001253 }
1254
1255 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001256 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001257 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1258 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001259 }
1260
1261 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001262 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001263 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1264 }
1265
1266 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1267 std::optional<int32_t> expectedFlags = std::nullopt) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001268 consumeMotionEvent(
1269 AllOf(WithMotionAction(ACTION_DOWN),
1270 testing::Conditional(expectedDisplayId.has_value(),
1271 WithDisplayId(*expectedDisplayId), testing::_),
1272 testing::Conditional(expectedFlags.has_value(), WithFlags(*expectedFlags),
1273 testing::_)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001274 }
1275
Svet Ganov5d3bc372020-01-26 23:11:07 -08001276 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001277 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1278 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001279 const int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001280 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001281 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1282 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001283 }
1284
1285 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001286 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001287 const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001288 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001289 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1290 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001291 }
1292
1293 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001294 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001295 consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1296 WithFlags(expectedFlags)));
Michael Wright3a240c42019-12-10 20:53:41 +00001297 }
1298
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001299 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1300 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001301 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE),
1302 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001303 }
1304
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001305 void consumeMotionOutsideWithZeroedCoords() {
1306 consumeMotionEvent(
1307 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE), WithRawCoords(0, 0)));
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001308 }
1309
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001310 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1311 ASSERT_NE(mInputReceiver, nullptr)
1312 << "Cannot consume events from a window with no receiver";
1313 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1314 }
1315
Prabir Pradhan99987712020-11-10 18:43:05 -08001316 void consumeCaptureEvent(bool hasCapture) {
1317 ASSERT_NE(mInputReceiver, nullptr)
1318 << "Cannot consume events from a window with no receiver";
1319 mInputReceiver->consumeCaptureEvent(hasCapture);
1320 }
1321
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001322 const MotionEvent& consumeMotionEvent(
1323 const ::testing::Matcher<MotionEvent>& matcher = testing::_) {
1324 const InputEvent& event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
1325 if (event.getType() != InputEventType::MOTION) {
1326 LOG(FATAL) << "Instead of motion event, got " << event;
Prabir Pradhan5893d362023-11-17 04:30:40 +00001327 }
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001328 const auto& motionEvent = static_cast<const MotionEvent&>(event);
1329 EXPECT_THAT(motionEvent, matcher);
1330 return motionEvent;
chaviwd1c23182019-12-20 18:44:56 -08001331 }
1332
arthurhungb89ccb02020-12-30 16:19:01 +08001333 void consumeDragEvent(bool isExiting, float x, float y) {
1334 mInputReceiver->consumeDragEvent(isExiting, x, y);
1335 }
1336
Antonio Kantekf16f2832021-09-28 04:39:20 +00001337 void consumeTouchModeEvent(bool inTouchMode) {
1338 ASSERT_NE(mInputReceiver, nullptr)
1339 << "Cannot consume events from a window with no receiver";
1340 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1341 }
1342
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001343 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001344 if (mInputReceiver == nullptr) {
1345 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1346 return std::nullopt;
1347 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001348 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED, outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001349 }
1350
1351 void finishEvent(uint32_t sequenceNum) {
1352 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1353 mInputReceiver->finishEvent(sequenceNum);
1354 }
1355
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001356 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1357 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1358 mInputReceiver->sendTimeline(inputEventId, timeline);
1359 }
1360
Arthur Hungb92218b2018-08-14 12:00:21 +08001361 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001362 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001363 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001364 return; // Can't receive events if the window does not have input channel
1365 }
1366 ASSERT_NE(nullptr, mInputReceiver)
1367 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001368 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001369 }
1370
chaviwaf87b3e2019-10-01 16:59:28 -07001371 sp<IBinder> getToken() { return mInfo.token; }
1372
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001373 const std::string& getName() { return mName; }
1374
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001375 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001376 mInfo.ownerPid = ownerPid;
1377 mInfo.ownerUid = ownerUid;
1378 }
1379
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001380 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001381
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001382 void destroyReceiver() { mInputReceiver = nullptr; }
1383
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001384 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1385
chaviwd1c23182019-12-20 18:44:56 -08001386private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001387 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001388 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001389 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001390 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001391 friend class sp<FakeWindowHandle>;
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001392
1393 const InputEvent& consume(std::chrono::milliseconds timeout, bool handled = true) {
1394 if (mInputReceiver == nullptr) {
1395 LOG(FATAL) << "Cannot consume event from a window with no input event receiver";
1396 }
1397 InputEvent* event = mInputReceiver->consume(timeout, handled);
1398 if (event == nullptr) {
1399 LOG(FATAL) << "Consume failed: no event";
1400 }
1401 return *event;
1402 }
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001403};
1404
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001405std::atomic<int32_t> FakeWindowHandle::sId{1};
1406
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001407class FakeMonitorReceiver {
1408public:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001409 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId)
1410 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001411
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001412 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001413
1414 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001415 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1416 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001417 }
1418
1419 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001420 return mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001421 }
1422
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001423 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001424
1425 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001426 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1427 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001428 }
1429
1430 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001431 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1432 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001433 }
1434
1435 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001436 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1437 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001438 }
1439
1440 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001441 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001442 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1443 WithDisplayId(expectedDisplayId),
1444 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1445 }
1446
1447 void consumeMotionPointerDown(int32_t pointerIdx) {
1448 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1449 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001450 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1451 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001452 }
1453
1454 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001455 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001456 }
1457
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001458 MotionEvent* consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001459
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001460 void assertNoEvents() { mInputReceiver.assertNoEvents(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001461
1462private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001463 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001464};
1465
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001466static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001467 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001468 int32_t displayId = ADISPLAY_ID_NONE,
1469 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001470 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001471 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001472 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001473 KeyEvent event;
1474 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1475
1476 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001477 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001478 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1479 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001480
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001481 if (!allowKeyRepeat) {
1482 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1483 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001484 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001485 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001486}
1487
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001488static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1489 InputEventInjectionResult result =
1490 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1491 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1492 if (result != InputEventInjectionResult::TIMED_OUT) {
1493 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1494 }
1495}
1496
1497static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001498 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001499 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001500}
1501
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001502// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1503// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1504// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001505static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1506 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001507 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001508 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001509 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001510}
1511
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001512static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001513 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001514 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001515}
1516
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001517static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001518 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001519 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001520 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001521 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001522 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1523 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001524}
1525
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001526static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001527 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1528 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001529 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001530 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1531 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001532 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001533 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001534 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001535 MotionEventBuilder motionBuilder =
1536 MotionEventBuilder(action, source)
1537 .displayId(displayId)
1538 .eventTime(eventTime)
1539 .rawXCursorPosition(cursorPosition.x)
1540 .rawYCursorPosition(cursorPosition.y)
1541 .pointer(
1542 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1543 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1544 motionBuilder.downTime(eventTime);
1545 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001546
1547 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001548 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1549 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001550}
1551
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001552static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1553 int32_t displayId,
1554 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001555 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001556}
1557
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001558static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1559 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001560 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001561 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001562}
1563
Jackal Guof9696682018-10-05 12:23:23 +08001564static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1565 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1566 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001567 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1568 AINPUT_SOURCE_KEYBOARD, displayId, POLICY_FLAG_PASS_TO_USER, action,
1569 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001570
1571 return args;
1572}
1573
Josep del Riob3981622023-04-18 15:49:45 +00001574static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1575 int32_t displayId = ADISPLAY_ID_NONE) {
1576 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1577 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001578 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1579 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C,
1580 AMETA_META_ON, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001581
1582 return args;
1583}
1584
1585static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1586 int32_t displayId = ADISPLAY_ID_NONE) {
1587 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1588 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001589 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1590 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST,
1591 KEY_ASSISTANT, AMETA_NONE, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001592
1593 return args;
1594}
1595
Prabir Pradhan678438e2023-04-13 19:32:51 +00001596[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1597 int32_t displayId,
1598 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001599 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001600 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1601 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1602 }
1603
chaviwd1c23182019-12-20 18:44:56 -08001604 PointerProperties pointerProperties[pointerCount];
1605 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001606
chaviwd1c23182019-12-20 18:44:56 -08001607 for (size_t i = 0; i < pointerCount; i++) {
1608 pointerProperties[i].clear();
1609 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001610 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001611
chaviwd1c23182019-12-20 18:44:56 -08001612 pointerCoords[i].clear();
1613 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1614 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1615 }
Jackal Guof9696682018-10-05 12:23:23 +08001616
1617 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1618 // Define a valid motion event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001619 NotifyMotionArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, source,
1620 displayId, POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0,
1621 /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001622 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001623 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001624 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001625 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001626
1627 return args;
1628}
1629
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001630static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1631 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1632}
1633
chaviwd1c23182019-12-20 18:44:56 -08001634static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1635 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1636}
1637
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001638static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1639 const PointerCaptureRequest& request) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001640 return NotifyPointerCaptureChangedArgs(InputEvent::nextId(), systemTime(SYSTEM_TIME_MONOTONIC),
1641 request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001642}
1643
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001644} // namespace
1645
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001646/**
1647 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1648 * broken channel.
1649 */
1650TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1651 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1652 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001653 sp<FakeWindowHandle>::make(application, mDispatcher,
1654 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001655
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001656 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001657
1658 // Window closes its channel, but the window remains.
1659 window->destroyReceiver();
1660 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1661}
1662
Arthur Hungb92218b2018-08-14 12:00:21 +08001663TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001664 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001665 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1666 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001667
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001668 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001669 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001670 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001671 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001672
1673 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001674 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001675}
1676
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001677TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1678 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001679 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1680 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001681
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001682 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001683 // Inject a MotionEvent to an unknown display.
1684 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001685 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001686 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1687
1688 // Window should receive motion event.
1689 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1690}
1691
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001692/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001693 * Calling onWindowInfosChanged once should not cause any issues.
1694 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001695 * called twice.
1696 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001697TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001698 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001699 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1700 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001701 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001702
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001703 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001704 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001705 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001706 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001707 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001708
1709 // Window should receive motion event.
1710 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1711}
1712
1713/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001714 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001715 */
1716TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001717 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001718 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1719 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001720 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001721
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001722 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1723 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001724 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001725 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001726 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001727 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001728
1729 // Window should receive motion event.
1730 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1731}
1732
Arthur Hungb92218b2018-08-14 12:00:21 +08001733// The foreground window should receive the first touch down event.
1734TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001735 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001736 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001737 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001738 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001739 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001740
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001741 mDispatcher->onWindowInfosChanged(
1742 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001743 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001744 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001745 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001746
1747 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001748 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001749 windowSecond->assertNoEvents();
1750}
1751
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001752/**
1753 * Two windows: A top window, and a wallpaper behind the window.
1754 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1755 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001756 * 1. foregroundWindow <-- dup touch to wallpaper
1757 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001758 */
1759TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1760 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1761 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001762 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001763 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001764 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001765 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001766 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001767
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001768 mDispatcher->onWindowInfosChanged(
1769 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001770 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001771 injectMotionEvent(*mDispatcher,
1772 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1773 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
1774 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001775 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1776
1777 // Both foreground window and its wallpaper should receive the touch down
1778 foregroundWindow->consumeMotionDown();
1779 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1780
1781 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001782 injectMotionEvent(*mDispatcher,
1783 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1784 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
1785 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001786 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1787
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001788 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001789 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1790
1791 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001792 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001793 foregroundWindow->consumeMotionCancel();
1794 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1795 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1796}
1797
1798/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001799 * Two fingers down on the window, and lift off the first finger.
1800 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1801 * contains a single pointer.
1802 */
1803TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1804 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1805 sp<FakeWindowHandle> window =
1806 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1807
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001808 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001809 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001810 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1811 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1812 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001813 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001814 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1815 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1816 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1817 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001818 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001819 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1820 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1821 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1822 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001823 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1824 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1825 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1826
1827 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001828 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001829 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1830 window->consumeMotionEvent(
1831 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1832}
1833
1834/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001835 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1836 * with the following differences:
1837 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1838 * clean up the connection.
1839 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1840 * Ensure that there's no crash in the dispatcher.
1841 */
1842TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1843 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1844 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001845 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001846 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001847 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001848 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001849 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001850
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001851 mDispatcher->onWindowInfosChanged(
1852 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001853 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001854 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001855 {100, 200}))
1856 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1857
1858 // Both foreground window and its wallpaper should receive the touch down
1859 foregroundWindow->consumeMotionDown();
1860 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1861
1862 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001863 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001864 ADISPLAY_ID_DEFAULT, {110, 200}))
1865 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1866
1867 foregroundWindow->consumeMotionMove();
1868 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1869
1870 // Wallpaper closes its channel, but the window remains.
1871 wallpaperWindow->destroyReceiver();
1872 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1873
1874 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1875 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001876 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001877 foregroundWindow->consumeMotionCancel();
1878}
1879
Arthur Hungc539dbb2022-12-08 07:45:36 +00001880class ShouldSplitTouchFixture : public InputDispatcherTest,
1881 public ::testing::WithParamInterface<bool> {};
1882INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1883 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001884/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001885 * A single window that receives touch (on top), and a wallpaper window underneath it.
1886 * The top window gets a multitouch gesture.
1887 * Ensure that wallpaper gets the same gesture.
1888 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001889TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001890 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001891 sp<FakeWindowHandle> foregroundWindow =
1892 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1893 foregroundWindow->setDupTouchToWallpaper(true);
1894 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001895
1896 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001897 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001898 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001899
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001900 mDispatcher->onWindowInfosChanged(
1901 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001902
1903 // Touch down on top window
1904 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001905 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001906 {100, 100}))
1907 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1908
1909 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001910 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001911 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1912
1913 // Second finger down on the top window
1914 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001915 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001916 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001917 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1918 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001919 .build();
1920 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001921 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001922 InputEventInjectionSync::WAIT_FOR_RESULT))
1923 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1924
Harry Cutts33476232023-01-30 19:57:29 +00001925 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1926 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001927 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001928
1929 const MotionEvent secondFingerUpEvent =
1930 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1931 .displayId(ADISPLAY_ID_DEFAULT)
1932 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001933 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1934 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001935 .build();
1936 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001937 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001938 InputEventInjectionSync::WAIT_FOR_RESULT))
1939 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1940 foregroundWindow->consumeMotionPointerUp(0);
1941 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1942
1943 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001944 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001945 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1946 AINPUT_SOURCE_TOUCHSCREEN)
1947 .displayId(ADISPLAY_ID_DEFAULT)
1948 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001949 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001950 .x(100)
1951 .y(100))
1952 .build(),
1953 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001954 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1955 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1956 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001957}
1958
1959/**
1960 * Two windows: a window on the left and window on the right.
1961 * A third window, wallpaper, is behind both windows, and spans both top windows.
1962 * The first touch down goes to the left window. A second pointer touches down on the right window.
1963 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1964 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1965 * ACTION_POINTER_DOWN(1).
1966 */
1967TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1968 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1969 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001970 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001971 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001972 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001973
1974 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001975 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001976 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001977 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001978
1979 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001980 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001981 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001982 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001983
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001984 mDispatcher->onWindowInfosChanged(
1985 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1986 {},
1987 0,
1988 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001989
1990 // Touch down on left window
1991 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001992 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001993 {100, 100}))
1994 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1995
1996 // Both foreground window and its wallpaper should receive the touch down
1997 leftWindow->consumeMotionDown();
1998 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1999
2000 // Second finger down on the right window
2001 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002002 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002003 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002004 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2005 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002006 .build();
2007 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002008 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002009 InputEventInjectionSync::WAIT_FOR_RESULT))
2010 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2011
2012 leftWindow->consumeMotionMove();
2013 // Since the touch is split, right window gets ACTION_DOWN
2014 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002015 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002016 expectedWallpaperFlags);
2017
2018 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002019 mDispatcher->onWindowInfosChanged(
2020 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002021 leftWindow->consumeMotionCancel();
2022 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2023 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2024
2025 // The pointer that's still down on the right window moves, and goes to the right window only.
2026 // As far as the dispatcher's concerned though, both pointers are still present.
2027 const MotionEvent secondFingerMoveEvent =
2028 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2029 .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(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002032 .build();
2033 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002034 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002035 InputEventInjectionSync::WAIT_FOR_RESULT));
2036 rightWindow->consumeMotionMove();
2037
2038 leftWindow->assertNoEvents();
2039 rightWindow->assertNoEvents();
2040 wallpaperWindow->assertNoEvents();
2041}
2042
Arthur Hungc539dbb2022-12-08 07:45:36 +00002043/**
2044 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2045 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2046 * The right window should receive ACTION_DOWN.
2047 */
2048TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002049 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002050 sp<FakeWindowHandle> leftWindow =
2051 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2052 leftWindow->setFrame(Rect(0, 0, 200, 200));
2053 leftWindow->setDupTouchToWallpaper(true);
2054 leftWindow->setSlippery(true);
2055
2056 sp<FakeWindowHandle> rightWindow =
2057 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2058 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002059
2060 sp<FakeWindowHandle> wallpaperWindow =
2061 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2062 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002063
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002064 mDispatcher->onWindowInfosChanged(
2065 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2066 {},
2067 0,
2068 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002069
Arthur Hungc539dbb2022-12-08 07:45:36 +00002070 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002071 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002072 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002073 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002074 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002075
2076 // Both foreground window and its wallpaper should receive the touch down
2077 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002078 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2079
Arthur Hungc539dbb2022-12-08 07:45:36 +00002080 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002081 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002082 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002083 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002084 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2085
Arthur Hungc539dbb2022-12-08 07:45:36 +00002086 leftWindow->consumeMotionCancel();
2087 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2088 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002089}
2090
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002091/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002092 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2093 * interactive, it might stop sending this flag.
2094 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2095 * to have a consistent input stream.
2096 *
2097 * Test procedure:
2098 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2099 * DOWN (new gesture).
2100 *
2101 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2102 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2103 *
2104 * We technically just need a single window here, but we are using two windows (spy on top and a
2105 * regular window below) to emulate the actual situation where it happens on the device.
2106 */
2107TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2108 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2109 sp<FakeWindowHandle> spyWindow =
2110 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2111 spyWindow->setFrame(Rect(0, 0, 200, 200));
2112 spyWindow->setTrustedOverlay(true);
2113 spyWindow->setSpy(true);
2114
2115 sp<FakeWindowHandle> window =
2116 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2117 window->setFrame(Rect(0, 0, 200, 200));
2118
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002119 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002120 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002121
2122 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002123 mDispatcher->notifyMotion(
2124 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2125 .deviceId(touchDeviceId)
2126 .policyFlags(DEFAULT_POLICY_FLAGS)
2127 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2128 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002129
Prabir Pradhan678438e2023-04-13 19:32:51 +00002130 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2131 .deviceId(touchDeviceId)
2132 .policyFlags(DEFAULT_POLICY_FLAGS)
2133 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2134 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2135 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002136 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2137 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2138 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2139 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2140
2141 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002142 mDispatcher->notifyMotion(
2143 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2144 .deviceId(touchDeviceId)
2145 .policyFlags(0)
2146 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2147 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2148 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002149 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2150 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2151
2152 // We don't need to reset the device to reproduce the issue, but the reset event typically
2153 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002154 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002155
2156 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002157 mDispatcher->notifyMotion(
2158 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2159 .deviceId(touchDeviceId)
2160 .policyFlags(DEFAULT_POLICY_FLAGS)
2161 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2162 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002163 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2164 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2165
2166 // No more events
2167 spyWindow->assertNoEvents();
2168 window->assertNoEvents();
2169}
2170
2171/**
Linnan Li907ae732023-09-05 17:14:21 +08002172 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
2173 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2174 * interactive, it might stop sending this flag.
2175 * We've already ensured the consistency of the touch event in this case, and we should also ensure
2176 * the consistency of the hover event in this case.
2177 *
2178 * Test procedure:
2179 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
2180 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
2181 *
2182 * We expect to receive two full streams of hover events.
2183 */
2184TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
2185 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2186
2187 sp<FakeWindowHandle> window =
2188 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2189 window->setFrame(Rect(0, 0, 300, 300));
2190
2191 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2192
2193 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2194 .policyFlags(DEFAULT_POLICY_FLAGS)
2195 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2196 .build());
2197 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2198
2199 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2200 .policyFlags(DEFAULT_POLICY_FLAGS)
2201 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2202 .build());
2203 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2204
2205 // Send hover exit without the default policy flags.
2206 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2207 .policyFlags(0)
2208 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2209 .build());
2210
2211 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2212
2213 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
2214 // right event.
2215 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2216 .policyFlags(DEFAULT_POLICY_FLAGS)
2217 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
2218 .build());
2219 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2220
2221 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2222 .policyFlags(DEFAULT_POLICY_FLAGS)
2223 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2224 .build());
2225 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2226
2227 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2228 .policyFlags(DEFAULT_POLICY_FLAGS)
2229 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2230 .build());
2231 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2232}
2233
2234/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002235 * Two windows: a window on the left and a window on the right.
2236 * Mouse is hovered from the right window into the left window.
2237 * Next, we tap on the left window, where the cursor was last seen.
2238 * The second tap is done onto the right window.
2239 * The mouse and tap are from two different devices.
2240 * We technically don't need to set the downtime / eventtime for these events, but setting these
2241 * explicitly helps during debugging.
2242 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2243 * In the buggy implementation, a tap on the right window would cause a crash.
2244 */
2245TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2246 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2247 sp<FakeWindowHandle> leftWindow =
2248 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2249 leftWindow->setFrame(Rect(0, 0, 200, 200));
2250
2251 sp<FakeWindowHandle> rightWindow =
2252 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2253 rightWindow->setFrame(Rect(200, 0, 400, 200));
2254
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002255 mDispatcher->onWindowInfosChanged(
2256 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002257 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2258 // stale.
2259 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2260 const int32_t mouseDeviceId = 6;
2261 const int32_t touchDeviceId = 4;
2262 // Move the cursor from right
2263 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002264 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002265 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2266 AINPUT_SOURCE_MOUSE)
2267 .deviceId(mouseDeviceId)
2268 .downTime(baseTime + 10)
2269 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002270 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002271 .build()));
2272 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2273
2274 // .. to the left window
2275 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002276 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002277 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2278 AINPUT_SOURCE_MOUSE)
2279 .deviceId(mouseDeviceId)
2280 .downTime(baseTime + 10)
2281 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002282 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002283 .build()));
2284 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2285 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2286 // Now tap the left window
2287 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002288 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002289 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2290 AINPUT_SOURCE_TOUCHSCREEN)
2291 .deviceId(touchDeviceId)
2292 .downTime(baseTime + 40)
2293 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002294 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002295 .build()));
2296 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2297 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2298
2299 // release tap
2300 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002301 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002302 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2303 AINPUT_SOURCE_TOUCHSCREEN)
2304 .deviceId(touchDeviceId)
2305 .downTime(baseTime + 40)
2306 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002307 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002308 .build()));
2309 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2310
2311 // Tap the window on the right
2312 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002313 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002314 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2315 AINPUT_SOURCE_TOUCHSCREEN)
2316 .deviceId(touchDeviceId)
2317 .downTime(baseTime + 60)
2318 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002319 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002320 .build()));
2321 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2322
2323 // release tap
2324 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002325 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002326 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2327 AINPUT_SOURCE_TOUCHSCREEN)
2328 .deviceId(touchDeviceId)
2329 .downTime(baseTime + 60)
2330 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002331 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002332 .build()));
2333 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2334
2335 // No more events
2336 leftWindow->assertNoEvents();
2337 rightWindow->assertNoEvents();
2338}
2339
2340/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002341 * Start hovering in a window. While this hover is still active, make another window appear on top.
2342 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2343 * While the top window is present, the hovering is stopped.
2344 * Later, hovering gets resumed again.
2345 * Ensure that new hover gesture is handled correctly.
2346 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2347 * to the window that's currently being hovered over.
2348 */
2349TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2350 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2351 sp<FakeWindowHandle> window =
2352 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2353 window->setFrame(Rect(0, 0, 200, 200));
2354
2355 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002356 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002357
2358 // Start hovering in the window
2359 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2360 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2361 .build());
2362 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2363
2364 // Now, an obscuring window appears!
2365 sp<FakeWindowHandle> obscuringWindow =
2366 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2367 ADISPLAY_ID_DEFAULT,
2368 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2369 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2370 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2371 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2372 obscuringWindow->setNoInputChannel(true);
2373 obscuringWindow->setFocusable(false);
2374 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002375 mDispatcher->onWindowInfosChanged(
2376 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002377
2378 // While this new obscuring window is present, the hovering is stopped
2379 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2380 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2381 .build());
2382 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2383
2384 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002385 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002386
2387 // And a new hover gesture starts.
2388 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2389 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2390 .build());
2391 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2392}
2393
2394/**
2395 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2396 * the obscuring window.
2397 */
2398TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2399 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2400 sp<FakeWindowHandle> window =
2401 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2402 window->setFrame(Rect(0, 0, 200, 200));
2403
2404 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002405 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002406
2407 // Start hovering in the window
2408 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2409 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2410 .build());
2411 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2412
2413 // Now, an obscuring window appears!
2414 sp<FakeWindowHandle> obscuringWindow =
2415 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2416 ADISPLAY_ID_DEFAULT,
2417 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2418 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2419 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2420 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2421 obscuringWindow->setNoInputChannel(true);
2422 obscuringWindow->setFocusable(false);
2423 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002424 mDispatcher->onWindowInfosChanged(
2425 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002426
2427 // While this new obscuring window is present, the hovering continues. The event can't go to the
2428 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2429 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2430 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2431 .build());
2432 obscuringWindow->assertNoEvents();
2433 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2434
2435 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002436 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002437
2438 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2439 // so it should generate a HOVER_ENTER
2440 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2441 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2442 .build());
2443 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2444
2445 // Now the MOVE should be getting dispatched normally
2446 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2447 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2448 .build());
2449 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2450}
2451
2452/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002453 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2454 * events are delivered to the window.
2455 */
2456TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2457 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2458 sp<FakeWindowHandle> window =
2459 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2460 window->setFrame(Rect(0, 0, 200, 200));
2461 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2462
2463 // Start hovering in the window
2464 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2465 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2466 .build());
2467 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2468
2469 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2470 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2471 .build());
2472 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2473
2474 // Scroll with the mouse
2475 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2476 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2477 .build());
2478 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2479}
2480
2481using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2482
2483/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002484 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2485 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002486 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002487TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002488 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2489 sp<FakeWindowHandle> window =
2490 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2491 window->setFrame(Rect(0, 0, 200, 200));
2492
2493 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2494
2495 constexpr int32_t touchDeviceId = 4;
2496 constexpr int32_t stylusDeviceId = 2;
2497
2498 // Stylus down
2499 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2500 .deviceId(stylusDeviceId)
2501 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2502 .build());
2503 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2504
2505 // Touch down
2506 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2507 .deviceId(touchDeviceId)
2508 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2509 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002510
2511 // Touch move
2512 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2513 .deviceId(touchDeviceId)
2514 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2515 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002516 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002517
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002518 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002519 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2520 .deviceId(stylusDeviceId)
2521 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2522 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002523 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2524 WithCoords(101, 111)));
2525
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002526 window->assertNoEvents();
2527}
2528
2529/**
2530 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002531 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002532 * Similar test as above, but with added SPY window.
2533 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002534TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002535 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2536 sp<FakeWindowHandle> window =
2537 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2538 sp<FakeWindowHandle> spyWindow =
2539 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2540 spyWindow->setFrame(Rect(0, 0, 200, 200));
2541 spyWindow->setTrustedOverlay(true);
2542 spyWindow->setSpy(true);
2543 window->setFrame(Rect(0, 0, 200, 200));
2544
2545 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2546
2547 constexpr int32_t touchDeviceId = 4;
2548 constexpr int32_t stylusDeviceId = 2;
2549
2550 // Stylus down
2551 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2552 .deviceId(stylusDeviceId)
2553 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2554 .build());
2555 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2556 spyWindow->consumeMotionEvent(
2557 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2558
2559 // Touch down
2560 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2561 .deviceId(touchDeviceId)
2562 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2563 .build());
2564
2565 // Touch move
2566 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2567 .deviceId(touchDeviceId)
2568 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2569 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002570
2571 // Touch is ignored because stylus is already down
2572
2573 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002574 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2575 .deviceId(stylusDeviceId)
2576 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2577 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002578 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2579 WithCoords(101, 111)));
2580 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2581 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002582
2583 window->assertNoEvents();
2584 spyWindow->assertNoEvents();
2585}
2586
2587/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002588 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002589 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002590 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002591TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002592 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2593 sp<FakeWindowHandle> window =
2594 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2595 window->setFrame(Rect(0, 0, 200, 200));
2596
2597 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2598
2599 constexpr int32_t touchDeviceId = 4;
2600 constexpr int32_t stylusDeviceId = 2;
2601
2602 // Stylus down on the window
2603 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2604 .deviceId(stylusDeviceId)
2605 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2606 .build());
2607 window->consumeMotionEvent(
2608 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2609
2610 // Touch down on window
2611 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2612 .deviceId(touchDeviceId)
2613 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2614 .build());
2615 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2616 .deviceId(touchDeviceId)
2617 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2618 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002619
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002620 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002621
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002622 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002623 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2624 .deviceId(stylusDeviceId)
2625 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2626 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002627 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2628 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002629
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002630 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002631 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2632 .deviceId(touchDeviceId)
2633 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2634 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002635 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002636}
2637
2638/**
2639 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002640 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002641 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002642TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002643 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2644 sp<FakeWindowHandle> window =
2645 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2646 window->setFrame(Rect(0, 0, 200, 200));
2647
2648 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2649
2650 constexpr int32_t touchDeviceId = 4;
2651 constexpr int32_t stylusDeviceId = 2;
2652
2653 // Touch down on window
2654 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2655 .deviceId(touchDeviceId)
2656 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2657 .build());
2658 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2659 .deviceId(touchDeviceId)
2660 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2661 .build());
2662 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2663 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2664
2665 // Stylus hover on the window
2666 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2667 .deviceId(stylusDeviceId)
2668 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2669 .build());
2670 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2671 .deviceId(stylusDeviceId)
2672 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2673 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002674 // Stylus hover movement causes touch to be canceled
2675 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2676 WithCoords(141, 146)));
2677 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2678 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2679 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2680 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002681
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002682 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002683 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2684 .deviceId(touchDeviceId)
2685 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2686 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002687
2688 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002689}
2690
2691/**
2692 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2693 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2694 * become active.
2695 */
2696TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
2697 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2698 sp<FakeWindowHandle> window =
2699 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2700 window->setFrame(Rect(0, 0, 200, 200));
2701
2702 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2703
2704 constexpr int32_t stylusDeviceId1 = 3;
2705 constexpr int32_t stylusDeviceId2 = 5;
2706
2707 // Touch down on window
2708 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2709 .deviceId(stylusDeviceId1)
2710 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2711 .build());
2712 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2713 .deviceId(stylusDeviceId1)
2714 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2715 .build());
2716 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2717 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2718
2719 // Second stylus down
2720 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2721 .deviceId(stylusDeviceId2)
2722 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2723 .build());
2724 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2725 .deviceId(stylusDeviceId2)
2726 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2727 .build());
2728
2729 // First stylus is canceled, second one takes over.
2730 window->consumeMotionEvent(
2731 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2732 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2733 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2734
2735 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2736 .deviceId(stylusDeviceId1)
2737 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2738 .build());
2739 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002740 window->assertNoEvents();
2741}
2742
2743/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002744 * One window. Touch down on the window. Then, stylus down on the window from another device.
2745 * Ensure that is canceled, because stylus down should be preferred over touch.
2746 */
2747TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
2748 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2749 sp<FakeWindowHandle> window =
2750 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2751 window->setFrame(Rect(0, 0, 200, 200));
2752
2753 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2754
2755 constexpr int32_t touchDeviceId = 4;
2756 constexpr int32_t stylusDeviceId = 2;
2757
2758 // Touch down on window
2759 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2760 .deviceId(touchDeviceId)
2761 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2762 .build());
2763 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2764 .deviceId(touchDeviceId)
2765 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2766 .build());
2767 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2768 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2769
2770 // Stylus down on the window
2771 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2772 .deviceId(stylusDeviceId)
2773 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2774 .build());
2775 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2776 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2777
2778 // Subsequent stylus movements are delivered correctly
2779 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2780 .deviceId(stylusDeviceId)
2781 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2782 .build());
2783 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2784 WithCoords(101, 111)));
2785}
2786
2787/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002788 * Two windows: a window on the left and a window on the right.
2789 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2790 * down. Then, on the left window, also place second touch pointer down.
2791 * This test tries to reproduce a crash.
2792 * In the buggy implementation, second pointer down on the left window would cause a crash.
2793 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002794TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002795 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2796 sp<FakeWindowHandle> leftWindow =
2797 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2798 leftWindow->setFrame(Rect(0, 0, 200, 200));
2799
2800 sp<FakeWindowHandle> rightWindow =
2801 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2802 rightWindow->setFrame(Rect(200, 0, 400, 200));
2803
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002804 mDispatcher->onWindowInfosChanged(
2805 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002806
2807 const int32_t touchDeviceId = 4;
2808 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002809
2810 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002811 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2812 .deviceId(mouseDeviceId)
2813 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2814 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002815 leftWindow->consumeMotionEvent(
2816 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2817
2818 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002819 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2820 .deviceId(mouseDeviceId)
2821 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2822 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2823 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002824
2825 leftWindow->consumeMotionEvent(
2826 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2827 leftWindow->consumeMotionEvent(
2828 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2829
Prabir Pradhan678438e2023-04-13 19:32:51 +00002830 mDispatcher->notifyMotion(
2831 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2832 .deviceId(mouseDeviceId)
2833 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2834 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2835 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2836 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002837 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2838
2839 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002840 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2841 .deviceId(touchDeviceId)
2842 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2843 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002844 leftWindow->assertNoEvents();
2845
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002846 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2847
2848 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002849 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2850 .deviceId(touchDeviceId)
2851 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2852 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2853 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002854 // Since this is now a new splittable pointer going down on the left window, and it's coming
2855 // from a different device, the current gesture in the left window (pointer down) should first
2856 // be canceled.
2857 leftWindow->consumeMotionEvent(
2858 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002859 leftWindow->consumeMotionEvent(
2860 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2861 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2862 // current implementation.
2863 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2864 rightWindow->consumeMotionEvent(
2865 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2866
2867 leftWindow->assertNoEvents();
2868 rightWindow->assertNoEvents();
2869}
2870
2871/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002872 * Two windows: a window on the left and a window on the right.
2873 * Mouse is hovered on the left window and stylus is hovered on the right window.
2874 */
2875TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2876 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2877 sp<FakeWindowHandle> leftWindow =
2878 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2879 leftWindow->setFrame(Rect(0, 0, 200, 200));
2880
2881 sp<FakeWindowHandle> rightWindow =
2882 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2883 rightWindow->setFrame(Rect(200, 0, 400, 200));
2884
2885 mDispatcher->onWindowInfosChanged(
2886 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2887
2888 const int32_t stylusDeviceId = 3;
2889 const int32_t mouseDeviceId = 6;
2890
2891 // Start hovering over the left window
2892 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2893 .deviceId(mouseDeviceId)
2894 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2895 .build());
2896 leftWindow->consumeMotionEvent(
2897 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2898
2899 // Stylus hovered on right window
2900 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2901 .deviceId(stylusDeviceId)
2902 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2903 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002904 rightWindow->consumeMotionEvent(
2905 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2906
2907 // Subsequent HOVER_MOVE events are dispatched correctly.
2908 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2909 .deviceId(mouseDeviceId)
2910 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2911 .build());
2912 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002913 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002914
2915 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2916 .deviceId(stylusDeviceId)
2917 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2918 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002919 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002920 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002921
2922 leftWindow->assertNoEvents();
2923 rightWindow->assertNoEvents();
2924}
2925
2926/**
2927 * Three windows: a window on the left and a window on the right.
2928 * And a spy window that's positioned above all of them.
2929 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2930 * Check the stream that's received by the spy.
2931 */
2932TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2933 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2934
2935 sp<FakeWindowHandle> spyWindow =
2936 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2937 spyWindow->setFrame(Rect(0, 0, 400, 400));
2938 spyWindow->setTrustedOverlay(true);
2939 spyWindow->setSpy(true);
2940
2941 sp<FakeWindowHandle> leftWindow =
2942 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2943 leftWindow->setFrame(Rect(0, 0, 200, 200));
2944
2945 sp<FakeWindowHandle> rightWindow =
2946 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2947
2948 rightWindow->setFrame(Rect(200, 0, 400, 200));
2949
2950 mDispatcher->onWindowInfosChanged(
2951 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2952
2953 const int32_t stylusDeviceId = 1;
2954 const int32_t touchDeviceId = 2;
2955
2956 // Stylus down on the left window
2957 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2958 .deviceId(stylusDeviceId)
2959 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2960 .build());
2961 leftWindow->consumeMotionEvent(
2962 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2963 spyWindow->consumeMotionEvent(
2964 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2965
2966 // Touch down on the right window
2967 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2968 .deviceId(touchDeviceId)
2969 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2970 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002971 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002972 rightWindow->consumeMotionEvent(
2973 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002974
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002975 // Spy window does not receive touch events, because stylus events take precedence, and it
2976 // already has an active stylus gesture.
2977
2978 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002979 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2980 .deviceId(stylusDeviceId)
2981 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2982 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002983 leftWindow->consumeMotionEvent(
2984 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2985 spyWindow->consumeMotionEvent(
2986 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002987
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002988 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002989 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2990 .deviceId(touchDeviceId)
2991 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2992 .build());
2993 rightWindow->consumeMotionEvent(
2994 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002995
2996 spyWindow->assertNoEvents();
2997 leftWindow->assertNoEvents();
2998 rightWindow->assertNoEvents();
2999}
3000
3001/**
3002 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3003 * both.
3004 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003005 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003006 * At the same time, left and right should be getting independent streams of hovering and touch,
3007 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003008 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003009TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003010 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3011
3012 sp<FakeWindowHandle> spyWindow =
3013 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3014 spyWindow->setFrame(Rect(0, 0, 400, 400));
3015 spyWindow->setTrustedOverlay(true);
3016 spyWindow->setSpy(true);
3017
3018 sp<FakeWindowHandle> leftWindow =
3019 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3020 leftWindow->setFrame(Rect(0, 0, 200, 200));
3021
3022 sp<FakeWindowHandle> rightWindow =
3023 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3024 rightWindow->setFrame(Rect(200, 0, 400, 200));
3025
3026 mDispatcher->onWindowInfosChanged(
3027 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3028
3029 const int32_t stylusDeviceId = 1;
3030 const int32_t touchDeviceId = 2;
3031
3032 // Stylus hover on the left window
3033 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3034 .deviceId(stylusDeviceId)
3035 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3036 .build());
3037 leftWindow->consumeMotionEvent(
3038 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3039 spyWindow->consumeMotionEvent(
3040 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3041
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003042 // Touch down on the right window. Spy doesn't receive this touch because it already has
3043 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003044 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3045 .deviceId(touchDeviceId)
3046 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3047 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003048 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003049 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003050 rightWindow->consumeMotionEvent(
3051 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3052
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003053 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003054 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3055 .deviceId(stylusDeviceId)
3056 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3057 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003058 leftWindow->consumeMotionEvent(
3059 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003060 spyWindow->consumeMotionEvent(
3061 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003062
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003063 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003064 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3065 .deviceId(touchDeviceId)
3066 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3067 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003068 rightWindow->consumeMotionEvent(
3069 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3070
3071 spyWindow->assertNoEvents();
3072 leftWindow->assertNoEvents();
3073 rightWindow->assertNoEvents();
3074}
3075
3076/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003077 * On a single window, use two different devices: mouse and touch.
3078 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3079 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3080 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3081 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3082 * represent a new gesture.
3083 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003084TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003085 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3086 sp<FakeWindowHandle> window =
3087 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3088 window->setFrame(Rect(0, 0, 400, 400));
3089
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003090 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003091
3092 const int32_t touchDeviceId = 4;
3093 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003094
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003095 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003096 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3097 .deviceId(touchDeviceId)
3098 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3099 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003100 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003101 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3102 .deviceId(touchDeviceId)
3103 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3104 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3105 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003106 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003107 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3108 .deviceId(touchDeviceId)
3109 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3110 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3111 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003112 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3113 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3114 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3115
3116 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003117 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3118 .deviceId(mouseDeviceId)
3119 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3120 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3121 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003122
3123 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003124 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003125 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3126
Prabir Pradhan678438e2023-04-13 19:32:51 +00003127 mDispatcher->notifyMotion(
3128 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3129 .deviceId(mouseDeviceId)
3130 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3131 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3132 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3133 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003134 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3135
3136 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003137 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3138 .deviceId(touchDeviceId)
3139 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3140 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3141 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003142 // Since we already canceled this touch gesture, it will be ignored until a completely new
3143 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3144 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3145 // However, mouse movements should continue to work.
3146 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3147 .deviceId(mouseDeviceId)
3148 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3149 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3150 .build());
3151 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3152
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003153 window->assertNoEvents();
3154}
3155
3156/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003157 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3158 * the injected event.
3159 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003160TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003161 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3162 sp<FakeWindowHandle> window =
3163 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3164 window->setFrame(Rect(0, 0, 400, 400));
3165
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003166 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003167
3168 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003169 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3170 // completion.
3171 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003172 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003173 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3174 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003175 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003176 .build()));
3177 window->consumeMotionEvent(
3178 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3179
3180 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3181 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003182 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3183 .deviceId(touchDeviceId)
3184 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3185 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003186
3187 window->consumeMotionEvent(
3188 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3189 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3190}
3191
3192/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003193 * This test is similar to the test above, but the sequence of injected events is different.
3194 *
3195 * Two windows: a window on the left and a window on the right.
3196 * Mouse is hovered over the left window.
3197 * Next, we tap on the left window, where the cursor was last seen.
3198 *
3199 * After that, we inject one finger down onto the right window, and then a second finger down onto
3200 * the left window.
3201 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3202 * window (first), and then another on the left window (second).
3203 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3204 * In the buggy implementation, second finger down on the left window would cause a crash.
3205 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003206TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003207 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3208 sp<FakeWindowHandle> leftWindow =
3209 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3210 leftWindow->setFrame(Rect(0, 0, 200, 200));
3211
3212 sp<FakeWindowHandle> rightWindow =
3213 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3214 rightWindow->setFrame(Rect(200, 0, 400, 200));
3215
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003216 mDispatcher->onWindowInfosChanged(
3217 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003218
3219 const int32_t mouseDeviceId = 6;
3220 const int32_t touchDeviceId = 4;
3221 // Hover over the left window. Keep the cursor there.
3222 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003223 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003224 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3225 AINPUT_SOURCE_MOUSE)
3226 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003227 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003228 .build()));
3229 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3230
3231 // Tap on left window
3232 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003233 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003234 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3235 AINPUT_SOURCE_TOUCHSCREEN)
3236 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003237 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003238 .build()));
3239
3240 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003241 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003242 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3243 AINPUT_SOURCE_TOUCHSCREEN)
3244 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003245 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003246 .build()));
3247 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3248 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3249 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3250
3251 // First finger down on right window
3252 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003253 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003254 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3255 AINPUT_SOURCE_TOUCHSCREEN)
3256 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003257 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003258 .build()));
3259 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3260
3261 // Second finger down on the left window
3262 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003263 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003264 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3265 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003266 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3267 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003268 .build()));
3269 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3270 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3271
3272 // No more events
3273 leftWindow->assertNoEvents();
3274 rightWindow->assertNoEvents();
3275}
3276
3277/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003278 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3279 * While the touch is down, new hover events from the stylus device should be ignored. After the
3280 * touch is gone, stylus hovering should start working again.
3281 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003282TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003283 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3284 sp<FakeWindowHandle> window =
3285 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3286 window->setFrame(Rect(0, 0, 200, 200));
3287
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003288 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003289
3290 const int32_t stylusDeviceId = 5;
3291 const int32_t touchDeviceId = 4;
3292 // Start hovering with stylus
3293 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003294 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003295 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003296 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003297 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003298 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003299 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003300
3301 // Finger down on the window
3302 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003303 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003304 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003305 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003306 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003307 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003308 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003309
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003310 // Continue hovering with stylus.
3311 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003312 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003313 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3314 AINPUT_SOURCE_STYLUS)
3315 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003316 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003317 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003318 // Hovers continue to work
3319 window->consumeMotionEvent(
3320 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003321
3322 // Lift up the finger
3323 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003324 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003325 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3326 AINPUT_SOURCE_TOUCHSCREEN)
3327 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003328 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003329 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003330
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003331 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003332 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003333 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3334 AINPUT_SOURCE_STYLUS)
3335 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003336 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003337 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003338 window->consumeMotionEvent(
3339 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003340 window->assertNoEvents();
3341}
3342
3343/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003344 * A spy window above a window with no input channel.
3345 * Start hovering with a stylus device, and then tap with it.
3346 * Ensure spy window receives the entire sequence.
3347 */
3348TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3349 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3350 sp<FakeWindowHandle> spyWindow =
3351 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3352 spyWindow->setFrame(Rect(0, 0, 200, 200));
3353 spyWindow->setTrustedOverlay(true);
3354 spyWindow->setSpy(true);
3355 sp<FakeWindowHandle> window =
3356 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3357 window->setNoInputChannel(true);
3358 window->setFrame(Rect(0, 0, 200, 200));
3359
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003360 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003361
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003362 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003363 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3364 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3365 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003366 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3367 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003368 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3369 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3370 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003371 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3372
3373 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003374 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3375 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3376 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003377 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3378
3379 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003380 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3381 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3382 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003383 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3384
3385 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003386 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3387 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3388 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003389 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3390 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003391 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3392 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3393 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003394 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3395
3396 // No more events
3397 spyWindow->assertNoEvents();
3398 window->assertNoEvents();
3399}
3400
3401/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003402 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3403 * rejected. But since we already have an ongoing gesture, this event should be processed.
3404 * This prevents inconsistent events being handled inside the dispatcher.
3405 */
3406TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3407 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3408
3409 sp<FakeWindowHandle> window =
3410 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3411 window->setFrame(Rect(0, 0, 200, 200));
3412
3413 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3414
3415 // Start hovering with stylus
3416 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3417 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3418 .build());
3419 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3420
3421 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3422 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3423 .build();
3424 // Make this 'hoverExit' event stale
3425 mFakePolicy->setStaleEventTimeout(100ms);
3426 std::this_thread::sleep_for(100ms);
3427
3428 // It shouldn't be dropped by the dispatcher, even though it's stale.
3429 mDispatcher->notifyMotion(hoverExit);
3430 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3431
3432 // Stylus starts hovering again! There should be no crash.
3433 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3434 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3435 .build());
3436 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3437}
3438
3439/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003440 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3441 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3442 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3443 * While the mouse is down, new move events from the touch device should be ignored.
3444 */
3445TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3446 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3447 sp<FakeWindowHandle> spyWindow =
3448 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3449 spyWindow->setFrame(Rect(0, 0, 200, 200));
3450 spyWindow->setTrustedOverlay(true);
3451 spyWindow->setSpy(true);
3452 sp<FakeWindowHandle> window =
3453 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3454 window->setFrame(Rect(0, 0, 200, 200));
3455
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003456 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003457
3458 const int32_t mouseDeviceId = 7;
3459 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003460
3461 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003462 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3463 .deviceId(mouseDeviceId)
3464 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3465 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003466 spyWindow->consumeMotionEvent(
3467 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3468 window->consumeMotionEvent(
3469 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3470
3471 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003472 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3473 .deviceId(touchDeviceId)
3474 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3475 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003476 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3477 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3478 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3479 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3480
Prabir Pradhan678438e2023-04-13 19:32:51 +00003481 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3482 .deviceId(touchDeviceId)
3483 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3484 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003485 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3486 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3487
3488 // Pilfer the stream
3489 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3490 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3491
Prabir Pradhan678438e2023-04-13 19:32:51 +00003492 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3493 .deviceId(touchDeviceId)
3494 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3495 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003496 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3497
3498 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003499 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3500 .deviceId(mouseDeviceId)
3501 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3502 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3503 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003504
3505 spyWindow->consumeMotionEvent(
3506 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3507 spyWindow->consumeMotionEvent(
3508 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3509 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3510
Prabir Pradhan678438e2023-04-13 19:32:51 +00003511 mDispatcher->notifyMotion(
3512 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3513 .deviceId(mouseDeviceId)
3514 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3515 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3516 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3517 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003518 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3519 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3520
3521 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003522 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3523 .deviceId(mouseDeviceId)
3524 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3525 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3526 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003527 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3528 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3529
3530 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003531 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3532 .deviceId(touchDeviceId)
3533 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3534 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003535
3536 // No more events
3537 spyWindow->assertNoEvents();
3538 window->assertNoEvents();
3539}
3540
3541/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003542 * On the display, have a single window, and also an area where there's no window.
3543 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3544 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3545 */
3546TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3547 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3548 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003549 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003550
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003551 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003552
3553 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003554 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003555
3556 mDispatcher->waitForIdle();
3557 window->assertNoEvents();
3558
3559 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003560 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003561 mDispatcher->waitForIdle();
3562 window->consumeMotionDown();
3563}
3564
3565/**
3566 * Same test as above, but instead of touching the empty space, the first touch goes to
3567 * non-touchable window.
3568 */
3569TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3570 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3571 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003572 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003573 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3574 window1->setTouchable(false);
3575 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003576 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003577 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3578
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003579 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003580
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003581 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003582 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003583
3584 mDispatcher->waitForIdle();
3585 window1->assertNoEvents();
3586 window2->assertNoEvents();
3587
3588 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003589 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003590 mDispatcher->waitForIdle();
3591 window2->consumeMotionDown();
3592}
3593
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003594/**
3595 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3596 * to the event time of the first ACTION_DOWN sent to the particular window.
3597 */
3598TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3599 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3600 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003601 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003602 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3603 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003604 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003605 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3606
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003607 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003608
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003609 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003610 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003611
3612 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003613
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00003614 const MotionEvent& motionEvent1 = window1->consumeMotionEvent();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003615 window2->assertNoEvents();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00003616 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
3617 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003618
3619 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003620 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003621 mDispatcher->waitForIdle();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00003622 const MotionEvent& motionEvent2 = window2->consumeMotionEvent();
3623 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003624 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00003625 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003626
3627 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003628 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003629 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003630 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003631
3632 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003633 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003634 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003635 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003636
3637 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3638 window1->consumeMotionMove();
3639 window1->assertNoEvents();
3640
3641 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003642 mDispatcher->notifyMotion(
3643 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003644 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003645 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003646
Prabir Pradhan678438e2023-04-13 19:32:51 +00003647 mDispatcher->notifyMotion(
3648 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003649 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003650 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003651}
3652
Garfield Tandf26e862020-07-01 20:18:19 -07003653TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003654 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003655 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003656 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003657 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003658 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003659 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003660 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003661
3662 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3663
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003664 mDispatcher->onWindowInfosChanged(
3665 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003666
3667 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003668 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003669 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003670 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3671 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003672 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003673 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003674 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003675
3676 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003677 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003678 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003679 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3680 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003681 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003682 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003683 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3684 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003685
3686 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003687 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003688 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003689 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3690 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003691 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003692 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003693 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3694 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003695
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003696 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003697 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003698 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3699 AINPUT_SOURCE_MOUSE)
3700 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3701 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003702 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003703 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003704 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003705
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003706 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003707 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003708 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3709 AINPUT_SOURCE_MOUSE)
3710 .buttonState(0)
3711 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003712 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003713 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003714 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003715
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003716 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003717 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003718 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3719 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003720 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003721 .build()));
3722 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3723
3724 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003725 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003726 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003727 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3728 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003729 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003730 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003731 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003732
3733 // No more events
3734 windowLeft->assertNoEvents();
3735 windowRight->assertNoEvents();
3736}
3737
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003738/**
3739 * Put two fingers down (and don't release them) and click the mouse button.
3740 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3741 * currently active gesture should be canceled, and the new one should proceed.
3742 */
3743TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3744 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3745 sp<FakeWindowHandle> window =
3746 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3747 window->setFrame(Rect(0, 0, 600, 800));
3748
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003749 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003750
3751 const int32_t touchDeviceId = 4;
3752 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003753
3754 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003755 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3756 .deviceId(touchDeviceId)
3757 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3758 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003759
Prabir Pradhan678438e2023-04-13 19:32:51 +00003760 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3761 .deviceId(touchDeviceId)
3762 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3763 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3764 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003765 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3766 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3767
3768 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003769 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3770 .deviceId(mouseDeviceId)
3771 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3772 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3773 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003774 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3775 WithPointerCount(2u)));
3776 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3777
Prabir Pradhan678438e2023-04-13 19:32:51 +00003778 mDispatcher->notifyMotion(
3779 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3780 .deviceId(mouseDeviceId)
3781 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3782 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3783 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3784 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003785 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3786
3787 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3788 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003789 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3790 .deviceId(touchDeviceId)
3791 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3792 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3793 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003794 window->assertNoEvents();
3795}
3796
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003797TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3798 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3799
3800 sp<FakeWindowHandle> spyWindow =
3801 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3802 spyWindow->setFrame(Rect(0, 0, 600, 800));
3803 spyWindow->setTrustedOverlay(true);
3804 spyWindow->setSpy(true);
3805 sp<FakeWindowHandle> window =
3806 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3807 window->setFrame(Rect(0, 0, 600, 800));
3808
3809 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003810 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003811
3812 // Send mouse cursor to the window
3813 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003814 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003815 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3816 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003817 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003818 .build()));
3819
3820 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3821 WithSource(AINPUT_SOURCE_MOUSE)));
3822 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3823 WithSource(AINPUT_SOURCE_MOUSE)));
3824
3825 window->assertNoEvents();
3826 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003827}
3828
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003829TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3830 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3831
3832 sp<FakeWindowHandle> spyWindow =
3833 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3834 spyWindow->setFrame(Rect(0, 0, 600, 800));
3835 spyWindow->setTrustedOverlay(true);
3836 spyWindow->setSpy(true);
3837 sp<FakeWindowHandle> window =
3838 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3839 window->setFrame(Rect(0, 0, 600, 800));
3840
3841 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003842 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003843
3844 // Send mouse cursor to the window
3845 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003846 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003847 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3848 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003849 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003850 .build()));
3851
3852 // Move mouse cursor
3853 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003854 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003855 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3856 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003857 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003858 .build()));
3859
3860 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3861 WithSource(AINPUT_SOURCE_MOUSE)));
3862 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3863 WithSource(AINPUT_SOURCE_MOUSE)));
3864 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3865 WithSource(AINPUT_SOURCE_MOUSE)));
3866 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3867 WithSource(AINPUT_SOURCE_MOUSE)));
3868 // Touch down on the window
3869 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003870 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003871 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3872 AINPUT_SOURCE_TOUCHSCREEN)
3873 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003874 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003875 .build()));
3876 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3877 WithSource(AINPUT_SOURCE_MOUSE)));
3878 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3879 WithSource(AINPUT_SOURCE_MOUSE)));
3880 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3881 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3882 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3883 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3884
3885 // pilfer the motion, retaining the gesture on the spy window.
3886 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3887 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3888 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3889
3890 // Touch UP on the window
3891 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003892 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003893 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3894 AINPUT_SOURCE_TOUCHSCREEN)
3895 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003896 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003897 .build()));
3898 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3899 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3900
3901 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3902 // to send a new gesture. It should again go to both windows (spy and the window below), just
3903 // like the first gesture did, before pilfering. The window configuration has not changed.
3904
3905 // One more tap - DOWN
3906 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003907 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003908 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3909 AINPUT_SOURCE_TOUCHSCREEN)
3910 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003911 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003912 .build()));
3913 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3914 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3915 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3916 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3917
3918 // Touch UP on the window
3919 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003920 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003921 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3922 AINPUT_SOURCE_TOUCHSCREEN)
3923 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003924 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003925 .build()));
3926 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3927 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3928 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3929 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3930
3931 window->assertNoEvents();
3932 spyWindow->assertNoEvents();
3933}
3934
Garfield Tandf26e862020-07-01 20:18:19 -07003935// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3936// directly in this test.
3937TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003938 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003939 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003940 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003941 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003942
3943 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3944
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003945 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003946
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003947 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003948 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003949 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3950 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003951 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003952 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003953 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003954 // 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 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3962 window->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 window->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 window->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 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3991
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003992 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3993 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3994 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003995 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003996 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3997 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003998 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003999 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004000 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004001}
4002
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004003/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004004 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
4005 * is generated.
4006 */
4007TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
4008 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4009 sp<FakeWindowHandle> window =
4010 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4011 window->setFrame(Rect(0, 0, 1200, 800));
4012
4013 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4014
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004015 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004016
4017 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004018 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004019 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4020 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004021 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004022 .build()));
4023 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4024
4025 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004026 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004027 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4028}
4029
4030/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004031 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4032 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004033TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4034 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4035 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004036 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4037 sp<FakeWindowHandle> window =
4038 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4039 window->setFrame(Rect(0, 0, 1200, 800));
4040
4041 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4042
4043 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4044
4045 MotionEventBuilder hoverEnterBuilder =
4046 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4047 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4048 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4049 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4050 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4051 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4052 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4053 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4054 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4055}
4056
4057/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004058 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4059 */
4060TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4061 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4062 sp<FakeWindowHandle> window =
4063 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4064 window->setFrame(Rect(0, 0, 100, 100));
4065
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004066 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004067
4068 const int32_t mouseDeviceId = 7;
4069 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004070
4071 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004072 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4073 .deviceId(mouseDeviceId)
4074 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4075 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004076 window->consumeMotionEvent(
4077 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4078
4079 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004080 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4081 .deviceId(touchDeviceId)
4082 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4083 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004084
4085 window->consumeMotionEvent(
4086 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4087 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4088}
4089
4090/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004091 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004092 * The tap causes a HOVER_EXIT event to be generated because the current event
4093 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004094 */
4095TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4096 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4097 sp<FakeWindowHandle> window =
4098 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4099 window->setFrame(Rect(0, 0, 100, 100));
4100
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004101 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004102 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4103 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4104 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004105 ASSERT_NO_FATAL_FAILURE(
4106 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4107 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004108
4109 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004110 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4111 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4112 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004113 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004114 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4115 WithSource(AINPUT_SOURCE_MOUSE))));
4116
4117 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004118 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4119 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4120
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004121 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4122 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4123 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004124 ASSERT_NO_FATAL_FAILURE(
4125 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4126 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4127}
4128
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004129TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4130 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4131 sp<FakeWindowHandle> windowDefaultDisplay =
4132 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4133 ADISPLAY_ID_DEFAULT);
4134 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4135 sp<FakeWindowHandle> windowSecondDisplay =
4136 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4137 SECOND_DISPLAY_ID);
4138 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4139
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004140 mDispatcher->onWindowInfosChanged(
4141 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004142
4143 // Set cursor position in window in default display and check that hover enter and move
4144 // events are generated.
4145 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004146 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004147 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4148 AINPUT_SOURCE_MOUSE)
4149 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004150 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004151 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004152 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004153
4154 // Remove all windows in secondary display and check that no event happens on window in
4155 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004156 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4157
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004158 windowDefaultDisplay->assertNoEvents();
4159
4160 // Move cursor position in window in default display and check that only hover move
4161 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004162 mDispatcher->onWindowInfosChanged(
4163 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004164 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004165 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004166 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4167 AINPUT_SOURCE_MOUSE)
4168 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004169 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004170 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004171 windowDefaultDisplay->consumeMotionEvent(
4172 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4173 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004174 windowDefaultDisplay->assertNoEvents();
4175}
4176
Garfield Tan00f511d2019-06-12 16:55:40 -07004177TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004178 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004179
4180 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004181 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004182 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004183 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004184 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004185 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004186
4187 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4188
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004189 mDispatcher->onWindowInfosChanged(
4190 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004191
4192 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4193 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004194 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004195 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004196 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004197 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004198 windowRight->assertNoEvents();
4199}
4200
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004201TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004202 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004203 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4204 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004205 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004206
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004207 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004208 setFocusedWindow(window);
4209
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004210 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004211
Prabir Pradhan678438e2023-04-13 19:32:51 +00004212 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004213
4214 // Window should receive key down event.
4215 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4216
4217 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4218 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004219 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004220 window->consumeKeyUp(ADISPLAY_ID_DEFAULT, AKEY_EVENT_FLAG_CANCELED);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004221}
4222
4223TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004224 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004225 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4226 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004227
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004228 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004229
Prabir Pradhan678438e2023-04-13 19:32:51 +00004230 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4231 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004232
4233 // Window should receive motion down event.
4234 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4235
4236 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4237 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004238 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004239 window->consumeMotionEvent(
4240 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004241}
4242
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004243TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4244 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4245 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4246 "Fake Window", ADISPLAY_ID_DEFAULT);
4247
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004248 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004249
4250 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4251 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4252 .build());
4253
4254 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4255
4256 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4257 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4258 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4259
4260 // After the device has been reset, a new hovering stream can be sent to the window
4261 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4262 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4263 .build());
4264 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4265}
4266
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004267TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4268 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004269 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4270 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004271 window->setFocusable(true);
4272
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004273 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004274 setFocusedWindow(window);
4275
4276 window->consumeFocusEvent(true);
4277
Prabir Pradhan678438e2023-04-13 19:32:51 +00004278 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004279 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4280 const nsecs_t injectTime = keyArgs.eventTime;
4281 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004282 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004283 // The dispatching time should be always greater than or equal to intercept key timeout.
4284 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4285 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4286 std::chrono::nanoseconds(interceptKeyTimeout).count());
4287}
4288
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004289/**
4290 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4291 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004292TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4293 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004294 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4295 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004296 window->setFocusable(true);
4297
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004298 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004299 setFocusedWindow(window);
4300
4301 window->consumeFocusEvent(true);
4302
Prabir Pradhan678438e2023-04-13 19:32:51 +00004303 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004304 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004305
4306 // Set a value that's significantly larger than the default consumption timeout. If the
4307 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4308 mFakePolicy->setInterceptKeyTimeout(600ms);
4309 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4310 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004311 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4312}
4313
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004314/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004315 * Two windows. First is a regular window. Second does not overlap with the first, and has
4316 * WATCH_OUTSIDE_TOUCH.
4317 * Both windows are owned by the same UID.
4318 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4319 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4320 */
4321TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4322 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004323 sp<FakeWindowHandle> window =
4324 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004325 window->setFrame(Rect{0, 0, 100, 100});
4326
4327 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004328 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004329 ADISPLAY_ID_DEFAULT);
4330 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4331 outsideWindow->setWatchOutsideTouch(true);
4332 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004333 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004334
4335 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004336 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4337 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4338 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004339 window->consumeMotionDown();
4340 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4341 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4342 outsideWindow->consumeMotionEvent(
4343 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00004344
4345 // Ensure outsideWindow doesn't get any more events for the gesture.
4346 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4347 ADISPLAY_ID_DEFAULT, {PointF{51, 51}}));
4348 window->consumeMotionMove();
4349 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004350}
4351
4352/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004353 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4354 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4355 * ACTION_OUTSIDE event is sent per gesture.
4356 */
4357TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4358 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4359 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004360 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4361 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004362 window->setWatchOutsideTouch(true);
4363 window->setFrame(Rect{0, 0, 100, 100});
4364 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004365 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4366 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004367 secondWindow->setFrame(Rect{100, 100, 200, 200});
4368 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004369 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4370 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004371 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004372 mDispatcher->onWindowInfosChanged(
4373 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004374
4375 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004376 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4377 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4378 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004379 window->assertNoEvents();
4380 secondWindow->assertNoEvents();
4381
4382 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4383 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004384 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4385 ADISPLAY_ID_DEFAULT,
4386 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004387 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4388 window->consumeMotionEvent(
4389 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004390 secondWindow->consumeMotionDown();
4391 thirdWindow->assertNoEvents();
4392
4393 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4394 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004395 mDispatcher->notifyMotion(
4396 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4397 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004398 window->assertNoEvents();
4399 secondWindow->consumeMotionMove();
4400 thirdWindow->consumeMotionDown();
4401}
4402
Prabir Pradhan814fe082022-07-22 20:22:18 +00004403TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4404 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004405 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4406 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004407 window->setFocusable(true);
4408
Patrick Williamsd828f302023-04-28 17:52:08 -05004409 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004410 setFocusedWindow(window);
4411
4412 window->consumeFocusEvent(true);
4413
Prabir Pradhan678438e2023-04-13 19:32:51 +00004414 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4415 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4416 mDispatcher->notifyKey(keyDown);
4417 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004418
4419 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4420 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4421
4422 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004423 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004424
4425 window->consumeFocusEvent(false);
4426
Prabir Pradhan678438e2023-04-13 19:32:51 +00004427 mDispatcher->notifyKey(keyDown);
4428 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004429 window->assertNoEvents();
4430}
4431
Arthur Hung96483742022-11-15 03:30:48 +00004432TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4433 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4434 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4435 "Fake Window", ADISPLAY_ID_DEFAULT);
4436 // Ensure window is non-split and have some transform.
4437 window->setPreventSplitting(true);
4438 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004439 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004440
4441 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004442 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004443 {50, 50}))
4444 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4445 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4446
4447 const MotionEvent secondFingerDownEvent =
4448 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4449 .displayId(ADISPLAY_ID_DEFAULT)
4450 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004451 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4452 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004453 .build();
4454 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004455 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004456 InputEventInjectionSync::WAIT_FOR_RESULT))
4457 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4458
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004459 const MotionEvent& event = window->consumeMotionEvent();
4460 EXPECT_EQ(POINTER_1_DOWN, event.getAction());
4461 EXPECT_EQ(70, event.getX(0)); // 50 + 20
4462 EXPECT_EQ(90, event.getY(0)); // 50 + 40
4463 EXPECT_EQ(-10, event.getX(1)); // -30 + 20
4464 EXPECT_EQ(-10, event.getY(1)); // -50 + 40
Arthur Hung96483742022-11-15 03:30:48 +00004465}
4466
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004467/**
4468 * Two windows: a splittable and a non-splittable.
4469 * The non-splittable window shouldn't receive any "incomplete" gestures.
4470 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4471 * The second pointer should be dropped because the initial window is splittable, so it won't get
4472 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4473 * "incomplete" gestures.
4474 */
4475TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4476 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4477 sp<FakeWindowHandle> leftWindow =
4478 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4479 ADISPLAY_ID_DEFAULT);
4480 leftWindow->setPreventSplitting(false);
4481 leftWindow->setFrame(Rect(0, 0, 100, 100));
4482 sp<FakeWindowHandle> rightWindow =
4483 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4484 ADISPLAY_ID_DEFAULT);
4485 rightWindow->setPreventSplitting(true);
4486 rightWindow->setFrame(Rect(100, 100, 200, 200));
4487 mDispatcher->onWindowInfosChanged(
4488 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4489
4490 // Touch down on left, splittable window
4491 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4492 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4493 .build());
4494 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4495
4496 mDispatcher->notifyMotion(
4497 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4498 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4499 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4500 .build());
4501 leftWindow->assertNoEvents();
4502 rightWindow->assertNoEvents();
4503}
4504
Harry Cuttsb166c002023-05-09 13:06:05 +00004505TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4506 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4507 sp<FakeWindowHandle> window =
4508 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4509 window->setFrame(Rect(0, 0, 400, 400));
4510 sp<FakeWindowHandle> trustedOverlay =
4511 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4512 ADISPLAY_ID_DEFAULT);
4513 trustedOverlay->setSpy(true);
4514 trustedOverlay->setTrustedOverlay(true);
4515
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004516 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004517
4518 // Start a three-finger touchpad swipe
4519 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4520 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4521 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4522 .build());
4523 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4524 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4525 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4526 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4527 .build());
4528 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4529 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4530 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4531 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4532 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4533 .build());
4534
4535 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4536 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4537 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4538
4539 // Move the swipe a bit
4540 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4541 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4542 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4543 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4544 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4545 .build());
4546
4547 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4548
4549 // End the swipe
4550 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4551 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4552 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4553 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4554 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4555 .build());
4556 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4557 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4558 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4559 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4560 .build());
4561 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4562 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4563 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4564 .build());
4565
4566 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4567 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4568 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4569
4570 window->assertNoEvents();
4571}
4572
4573TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4574 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4575 sp<FakeWindowHandle> window =
4576 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4577 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004578 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004579
4580 // Start a three-finger touchpad swipe
4581 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4582 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4583 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4584 .build());
4585 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4586 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4587 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4588 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4589 .build());
4590 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4591 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4592 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4593 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4594 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4595 .build());
4596
4597 // Move the swipe a bit
4598 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4599 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4600 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4601 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4602 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4603 .build());
4604
4605 // End the swipe
4606 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4607 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4608 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4609 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4610 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4611 .build());
4612 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4613 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4614 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4615 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4616 .build());
4617 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4618 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4619 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4620 .build());
4621
4622 window->assertNoEvents();
4623}
4624
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004625/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004626 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4627 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004628 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004629 */
4630TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4631 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4632 sp<FakeWindowHandle> window =
4633 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4634 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004635 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004636
4637 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4638 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4639 .downTime(baseTime + 10)
4640 .eventTime(baseTime + 10)
4641 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4642 .build());
4643
4644 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4645
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004646 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004647 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004648
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004649 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004650
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004651 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4652 .downTime(baseTime + 10)
4653 .eventTime(baseTime + 30)
4654 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4655 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4656 .build());
4657
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004658 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4659
4660 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004661 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4662 .downTime(baseTime + 10)
4663 .eventTime(baseTime + 40)
4664 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4665 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4666 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004667
4668 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4669
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004670 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4671 .downTime(baseTime + 10)
4672 .eventTime(baseTime + 50)
4673 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4674 .build());
4675
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004676 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4677
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004678 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4679 .downTime(baseTime + 60)
4680 .eventTime(baseTime + 60)
4681 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4682 .build());
4683
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004684 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004685}
4686
4687/**
Hu Guo771a7692023-09-17 20:51:08 +08004688 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4689 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4690 * its coordinates should be converted by the transform of the windows of target screen.
4691 */
4692TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4693 // This case will create a window and a spy window on the default display and mirror
4694 // window on the second display. cancel event is sent through spy window pilferPointers
4695 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4696
4697 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4698 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4699 spyWindowDefaultDisplay->setTrustedOverlay(true);
4700 spyWindowDefaultDisplay->setSpy(true);
4701
4702 sp<FakeWindowHandle> windowDefaultDisplay =
4703 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4704 ADISPLAY_ID_DEFAULT);
4705 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4706
4707 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4708 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4709
4710 // Add the windows to the dispatcher
4711 mDispatcher->onWindowInfosChanged(
4712 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4713 *windowSecondDisplay->getInfo()},
4714 {},
4715 0,
4716 0});
4717
4718 // Send down to ADISPLAY_ID_DEFAULT
4719 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4720 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4721 {100, 100}))
4722 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4723
4724 spyWindowDefaultDisplay->consumeMotionDown();
4725 windowDefaultDisplay->consumeMotionDown();
4726
4727 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4728
4729 // windowDefaultDisplay gets cancel
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004730 const MotionEvent& event = windowDefaultDisplay->consumeMotionEvent();
4731 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event.getAction());
Hu Guo771a7692023-09-17 20:51:08 +08004732
4733 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4734 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4735 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4736 // SECOND_DISPLAY_ID, the x and y coordinates are 200
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004737 EXPECT_EQ(100, event.getX(0));
4738 EXPECT_EQ(100, event.getY(0));
Hu Guo771a7692023-09-17 20:51:08 +08004739}
4740
4741/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004742 * Ensure the correct coordinate spaces are used by InputDispatcher.
4743 *
4744 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4745 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4746 * space.
4747 */
4748class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4749public:
4750 void SetUp() override {
4751 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004752 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004753 }
4754
4755 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4756 gui::DisplayInfo info;
4757 info.displayId = displayId;
4758 info.transform = transform;
4759 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004760 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004761 }
4762
4763 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4764 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004765 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004766 }
4767
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004768 void removeAllWindowsAndDisplays() {
4769 mDisplayInfos.clear();
4770 mWindowInfos.clear();
4771 }
4772
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004773 // Set up a test scenario where the display has a scaled projection and there are two windows
4774 // on the display.
4775 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4776 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4777 // respectively.
4778 ui::Transform displayTransform;
4779 displayTransform.set(2, 0, 0, 4);
4780 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4781
4782 std::shared_ptr<FakeApplicationHandle> application =
4783 std::make_shared<FakeApplicationHandle>();
4784
4785 // Add two windows to the display. Their frames are represented in the display space.
4786 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004787 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4788 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004789 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4790 addWindow(firstWindow);
4791
4792 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004793 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4794 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004795 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4796 addWindow(secondWindow);
4797 return {std::move(firstWindow), std::move(secondWindow)};
4798 }
4799
4800private:
4801 std::vector<gui::DisplayInfo> mDisplayInfos;
4802 std::vector<gui::WindowInfo> mWindowInfos;
4803};
4804
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004805TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004806 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4807 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004808 // selected so that if the hit test was performed with the point and the bounds being in
4809 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004810 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4811 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4812 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004813
4814 firstWindow->consumeMotionDown();
4815 secondWindow->assertNoEvents();
4816}
4817
4818// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4819// the event should be treated as being in the logical display space.
4820TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4821 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4822 // Send down to the first window. The point is represented in the logical display space. The
4823 // point is selected so that if the hit test was done in logical display space, then it would
4824 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004825 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004826 PointF{75 * 2, 55 * 4});
4827
4828 firstWindow->consumeMotionDown();
4829 secondWindow->assertNoEvents();
4830}
4831
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004832// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4833// event should be treated as being in the logical display space.
4834TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4835 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4836
4837 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4838 ui::Transform injectedEventTransform;
4839 injectedEventTransform.set(matrix);
4840 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4841 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4842
4843 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4844 .displayId(ADISPLAY_ID_DEFAULT)
4845 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004846 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004847 .x(untransformedPoint.x)
4848 .y(untransformedPoint.y))
4849 .build();
4850 event.transform(matrix);
4851
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004852 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004853 InputEventInjectionSync::WAIT_FOR_RESULT);
4854
4855 firstWindow->consumeMotionDown();
4856 secondWindow->assertNoEvents();
4857}
4858
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004859TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4860 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4861
4862 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004863 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4864 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4865 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004866
4867 firstWindow->assertNoEvents();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004868 const MotionEvent& event = secondWindow->consumeMotionEvent();
4869 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event.getAction());
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004870
4871 // Ensure that the events from the "getRaw" API are in logical display coordinates.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004872 EXPECT_EQ(300, event.getRawX(0));
4873 EXPECT_EQ(880, event.getRawY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004874
4875 // Ensure that the x and y values are in the window's coordinate space.
4876 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4877 // the logical display space. This will be the origin of the window space.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004878 EXPECT_EQ(100, event.getX(0));
4879 EXPECT_EQ(80, event.getY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004880}
4881
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004882TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
4883 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4884 // The monitor will always receive events in the logical display's coordinate space, because
4885 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00004886 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004887
4888 // Send down to the first window.
4889 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4890 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4891 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4892 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4893
4894 // Second pointer goes down on second window.
4895 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4896 ADISPLAY_ID_DEFAULT,
4897 {PointF{50, 100}, PointF{150, 220}}));
4898 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
4899 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
4900 {1, PointF{300, 880}}};
4901 monitor.consumeMotionEvent(
4902 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
4903
4904 mDispatcher->cancelCurrentTouch();
4905
4906 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4907 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
4908 monitor.consumeMotionEvent(
4909 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
4910}
4911
Prabir Pradhan1c29a092023-09-21 10:29:29 +00004912TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
4913 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4914
4915 // Send down to the first window.
4916 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4917 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4918 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4919
4920 // The pointer is transferred to the second window, and the second window receives it in the
4921 // correct coordinate space.
4922 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4923 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4924 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
4925}
4926
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00004927TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
4928 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4929
4930 // Send hover move to the second window, and ensure it shows up as hover enter.
4931 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4932 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4933 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4934 WithCoords(100, 80), WithRawCoords(300, 880)));
4935
4936 // Touch down at the same location and ensure a hover exit is synthesized.
4937 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4938 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4939 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4940 WithRawCoords(300, 880)));
4941 secondWindow->consumeMotionEvent(
4942 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4943 secondWindow->assertNoEvents();
4944 firstWindow->assertNoEvents();
4945}
4946
Prabir Pradhan453ae732023-10-13 14:30:14 +00004947// Same as above, but while the window is being mirrored.
4948TEST_F(InputDispatcherDisplayProjectionTest,
4949 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
4950 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4951
4952 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4953 ui::Transform secondDisplayTransform;
4954 secondDisplayTransform.set(matrix);
4955 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
4956
4957 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
4958 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
4959 addWindow(secondWindowClone);
4960
4961 // Send hover move to the second window, and ensure it shows up as hover enter.
4962 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4963 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4964 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4965 WithCoords(100, 80), WithRawCoords(300, 880)));
4966
4967 // Touch down at the same location and ensure a hover exit is synthesized for the correct
4968 // display.
4969 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4970 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4971 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4972 WithRawCoords(300, 880)));
4973 secondWindow->consumeMotionEvent(
4974 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4975 secondWindow->assertNoEvents();
4976 firstWindow->assertNoEvents();
4977}
4978
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00004979TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
4980 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4981
4982 // Send hover enter to second window
4983 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
4984 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4985 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4986 WithCoords(100, 80), WithRawCoords(300, 880)));
4987
4988 mDispatcher->cancelCurrentTouch();
4989
4990 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4991 WithRawCoords(300, 880)));
4992 secondWindow->assertNoEvents();
4993 firstWindow->assertNoEvents();
4994}
4995
Prabir Pradhan453ae732023-10-13 14:30:14 +00004996// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00004997TEST_F(InputDispatcherDisplayProjectionTest,
4998 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
4999 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5000
5001 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5002 ui::Transform secondDisplayTransform;
5003 secondDisplayTransform.set(matrix);
5004 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5005
5006 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5007 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5008 addWindow(secondWindowClone);
5009
5010 // Send hover enter to second window
5011 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5012 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5013 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5014 WithCoords(100, 80), WithRawCoords(300, 880),
5015 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5016
5017 mDispatcher->cancelCurrentTouch();
5018
5019 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
5020 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5021 WithRawCoords(300, 880),
5022 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5023 secondWindow->assertNoEvents();
5024 firstWindow->assertNoEvents();
5025}
5026
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005027/** Ensure consistent behavior of InputDispatcher in all orientations. */
5028class InputDispatcherDisplayOrientationFixture
5029 : public InputDispatcherDisplayProjectionTest,
5030 public ::testing::WithParamInterface<ui::Rotation> {};
5031
5032// This test verifies the touchable region of a window for all rotations of the display by tapping
5033// in different locations on the display, specifically points close to the four corners of a
5034// window.
5035TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
5036 constexpr static int32_t displayWidth = 400;
5037 constexpr static int32_t displayHeight = 800;
5038
5039 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5040
5041 const auto rotation = GetParam();
5042
5043 // Set up the display with the specified rotation.
5044 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5045 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5046 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5047 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5048 logicalDisplayWidth, logicalDisplayHeight);
5049 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5050
5051 // Create a window with its bounds determined in the logical display.
5052 const Rect frameInLogicalDisplay(100, 100, 200, 300);
5053 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
5054 sp<FakeWindowHandle> window =
5055 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5056 window->setFrame(frameInDisplay, displayTransform);
5057 addWindow(window);
5058
5059 // The following points in logical display space should be inside the window.
5060 static const std::array<vec2, 4> insidePoints{
5061 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5062 for (const auto pointInsideWindow : insidePoints) {
5063 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
5064 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005065 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5066 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5067 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005068 window->consumeMotionDown();
5069
Prabir Pradhan678438e2023-04-13 19:32:51 +00005070 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5071 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5072 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005073 window->consumeMotionUp();
5074 }
5075
5076 // The following points in logical display space should be outside the window.
5077 static const std::array<vec2, 5> outsidePoints{
5078 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
5079 for (const auto pointOutsideWindow : outsidePoints) {
5080 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
5081 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005082 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5083 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5084 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005085
Prabir Pradhan678438e2023-04-13 19:32:51 +00005086 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5087 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5088 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005089 }
5090 window->assertNoEvents();
5091}
5092
5093// Run the precision tests for all rotations.
5094INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
5095 InputDispatcherDisplayOrientationFixture,
5096 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
5097 ui::ROTATION_270),
5098 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
5099 return ftl::enum_string(testParamInfo.param);
5100 });
5101
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005102using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
5103 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005104
5105class TransferTouchFixture : public InputDispatcherTest,
5106 public ::testing::WithParamInterface<TransferFunction> {};
5107
5108TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07005109 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005110
5111 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005112 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005113 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5114 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005115 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005116 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005117 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5118 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005119 sp<FakeWindowHandle> wallpaper =
5120 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
5121 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005122 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005123 mDispatcher->onWindowInfosChanged(
5124 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005125
5126 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005127 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5128 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005129
Svet Ganov5d3bc372020-01-26 23:11:07 -08005130 // Only the first window should get the down event
5131 firstWindow->consumeMotionDown();
5132 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005133 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005134
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005135 // Transfer touch to the second window
5136 TransferFunction f = GetParam();
5137 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5138 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005139 // The first window gets cancel and the second gets down
5140 firstWindow->consumeMotionCancel();
5141 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005142 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005143
5144 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005145 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5146 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005147 // The first window gets no events and the second gets up
5148 firstWindow->assertNoEvents();
5149 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005150 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005151}
5152
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005153/**
5154 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
5155 * from. When we have spy windows, there are several windows to choose from: either spy, or the
5156 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
5157 * natural to the user.
5158 * In this test, we are sending a pointer to both spy window and first window. We then try to
5159 * transfer touch to the second window. The dispatcher should identify the first window as the
5160 * one that should lose the gesture, and therefore the action should be to move the gesture from
5161 * the first window to the second.
5162 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
5163 * the other API, as well.
5164 */
5165TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5166 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5167
5168 // Create a couple of windows + a spy window
5169 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005170 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005171 spyWindow->setTrustedOverlay(true);
5172 spyWindow->setSpy(true);
5173 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005174 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005175 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005176 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005177
5178 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005179 mDispatcher->onWindowInfosChanged(
5180 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005181
5182 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005183 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5184 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005185 // Only the first window and spy should get the down event
5186 spyWindow->consumeMotionDown();
5187 firstWindow->consumeMotionDown();
5188
5189 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
5190 // if f === 'transferTouch'.
5191 TransferFunction f = GetParam();
5192 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5193 ASSERT_TRUE(success);
5194 // The first window gets cancel and the second gets down
5195 firstWindow->consumeMotionCancel();
5196 secondWindow->consumeMotionDown();
5197
5198 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005199 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5200 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005201 // The first window gets no events and the second+spy get up
5202 firstWindow->assertNoEvents();
5203 spyWindow->consumeMotionUp();
5204 secondWindow->consumeMotionUp();
5205}
5206
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005207TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005208 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005209
5210 PointF touchPoint = {10, 10};
5211
5212 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005213 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005214 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5215 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005216 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005217 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005218 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5219 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005220 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005221
5222 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005223 mDispatcher->onWindowInfosChanged(
5224 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005225
5226 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005227 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5228 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5229 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005230 // Only the first window should get the down event
5231 firstWindow->consumeMotionDown();
5232 secondWindow->assertNoEvents();
5233
5234 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005235 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5236 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005237 // Only the first window should get the pointer down event
5238 firstWindow->consumeMotionPointerDown(1);
5239 secondWindow->assertNoEvents();
5240
5241 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005242 TransferFunction f = GetParam();
5243 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5244 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005245 // The first window gets cancel and the second gets down and pointer down
5246 firstWindow->consumeMotionCancel();
5247 secondWindow->consumeMotionDown();
5248 secondWindow->consumeMotionPointerDown(1);
5249
5250 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005251 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5252 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005253 // The first window gets nothing and the second gets pointer up
5254 firstWindow->assertNoEvents();
5255 secondWindow->consumeMotionPointerUp(1);
5256
5257 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005258 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5259 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005260 // The first window gets nothing and the second gets up
5261 firstWindow->assertNoEvents();
5262 secondWindow->consumeMotionUp();
5263}
5264
Arthur Hungc539dbb2022-12-08 07:45:36 +00005265TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5266 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5267
5268 // Create a couple of windows
5269 sp<FakeWindowHandle> firstWindow =
5270 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5271 ADISPLAY_ID_DEFAULT);
5272 firstWindow->setDupTouchToWallpaper(true);
5273 sp<FakeWindowHandle> secondWindow =
5274 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5275 ADISPLAY_ID_DEFAULT);
5276 secondWindow->setDupTouchToWallpaper(true);
5277
5278 sp<FakeWindowHandle> wallpaper1 =
5279 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5280 wallpaper1->setIsWallpaper(true);
5281
5282 sp<FakeWindowHandle> wallpaper2 =
5283 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5284 wallpaper2->setIsWallpaper(true);
5285 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005286 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5287 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5288 {},
5289 0,
5290 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005291
5292 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005293 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5294 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005295
5296 // Only the first window should get the down event
5297 firstWindow->consumeMotionDown();
5298 secondWindow->assertNoEvents();
5299 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5300 wallpaper2->assertNoEvents();
5301
5302 // Transfer touch focus to the second window
5303 TransferFunction f = GetParam();
5304 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5305 ASSERT_TRUE(success);
5306
5307 // The first window gets cancel and the second gets down
5308 firstWindow->consumeMotionCancel();
5309 secondWindow->consumeMotionDown();
5310 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5311 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5312
5313 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005314 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5315 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005316 // The first window gets no events and the second gets up
5317 firstWindow->assertNoEvents();
5318 secondWindow->consumeMotionUp();
5319 wallpaper1->assertNoEvents();
5320 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5321}
5322
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005323// For the cases of single pointer touch and two pointers non-split touch, the api's
5324// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5325// for the case where there are multiple pointers split across several windows.
5326INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5327 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005328 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5329 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005330 return dispatcher->transferTouch(destChannelToken,
5331 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005332 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005333 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5334 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005335 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005336 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005337 }));
5338
Svet Ganov5d3bc372020-01-26 23:11:07 -08005339TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005340 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005341
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005342 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005343 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5344 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005345 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005346
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005347 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005348 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5349 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005350 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005351
5352 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005353 mDispatcher->onWindowInfosChanged(
5354 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005355
5356 PointF pointInFirst = {300, 200};
5357 PointF pointInSecond = {300, 600};
5358
5359 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005360 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5361 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5362 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005363 // Only the first window should get the down event
5364 firstWindow->consumeMotionDown();
5365 secondWindow->assertNoEvents();
5366
5367 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005368 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5369 ADISPLAY_ID_DEFAULT,
5370 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005371 // The first window gets a move and the second a down
5372 firstWindow->consumeMotionMove();
5373 secondWindow->consumeMotionDown();
5374
5375 // Transfer touch focus to the second window
5376 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5377 // The first window gets cancel and the new gets pointer down (it already saw down)
5378 firstWindow->consumeMotionCancel();
5379 secondWindow->consumeMotionPointerDown(1);
5380
5381 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005382 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5383 ADISPLAY_ID_DEFAULT,
5384 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005385 // The first window gets nothing and the second gets pointer up
5386 firstWindow->assertNoEvents();
5387 secondWindow->consumeMotionPointerUp(1);
5388
5389 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005390 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5391 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005392 // The first window gets nothing and the second gets up
5393 firstWindow->assertNoEvents();
5394 secondWindow->consumeMotionUp();
5395}
5396
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005397// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5398// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5399// touch is not supported, so the touch should continue on those windows and the transferred-to
5400// window should get nothing.
5401TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5402 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5403
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005404 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005405 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5406 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005407 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005408
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005409 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005410 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5411 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005412 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005413
5414 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005415 mDispatcher->onWindowInfosChanged(
5416 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005417
5418 PointF pointInFirst = {300, 200};
5419 PointF pointInSecond = {300, 600};
5420
5421 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005422 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5423 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5424 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005425 // Only the first window should get the down event
5426 firstWindow->consumeMotionDown();
5427 secondWindow->assertNoEvents();
5428
5429 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005430 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5431 ADISPLAY_ID_DEFAULT,
5432 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005433 // The first window gets a move and the second a down
5434 firstWindow->consumeMotionMove();
5435 secondWindow->consumeMotionDown();
5436
5437 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005438 const bool transferred =
5439 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005440 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5441 ASSERT_FALSE(transferred);
5442 firstWindow->assertNoEvents();
5443 secondWindow->assertNoEvents();
5444
5445 // The rest of the dispatch should proceed as normal
5446 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005447 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5448 ADISPLAY_ID_DEFAULT,
5449 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005450 // The first window gets MOVE and the second gets pointer up
5451 firstWindow->consumeMotionMove();
5452 secondWindow->consumeMotionUp();
5453
5454 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005455 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5456 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005457 // The first window gets nothing and the second gets up
5458 firstWindow->consumeMotionUp();
5459 secondWindow->assertNoEvents();
5460}
5461
Arthur Hungabbb9d82021-09-01 14:52:30 +00005462// This case will create two windows and one mirrored window on the default display and mirror
5463// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5464// the windows info of second display before default display.
5465TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5466 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5467 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005468 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005469 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005470 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005471 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005472 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005473
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005474 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005475 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005476
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005477 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005478 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005479
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005480 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005481 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005482
5483 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005484 mDispatcher->onWindowInfosChanged(
5485 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5486 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5487 *secondWindowInPrimary->getInfo()},
5488 {},
5489 0,
5490 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005491
5492 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005493 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005494 {50, 50}))
5495 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5496
5497 // Window should receive motion event.
5498 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5499
5500 // Transfer touch focus
5501 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5502 secondWindowInPrimary->getToken()));
5503 // The first window gets cancel.
5504 firstWindowInPrimary->consumeMotionCancel();
5505 secondWindowInPrimary->consumeMotionDown();
5506
5507 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005508 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005509 ADISPLAY_ID_DEFAULT, {150, 50}))
5510 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5511 firstWindowInPrimary->assertNoEvents();
5512 secondWindowInPrimary->consumeMotionMove();
5513
5514 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005515 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005516 {150, 50}))
5517 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5518 firstWindowInPrimary->assertNoEvents();
5519 secondWindowInPrimary->consumeMotionUp();
5520}
5521
5522// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5523// 'transferTouch' api.
5524TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5525 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5526 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005527 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005528 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005529 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005530 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005531 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005532
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005533 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005534 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005535
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005536 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005537 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005538
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005539 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005540 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005541
5542 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005543 mDispatcher->onWindowInfosChanged(
5544 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5545 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5546 *secondWindowInPrimary->getInfo()},
5547 {},
5548 0,
5549 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005550
5551 // Touch on second display.
5552 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005553 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5554 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005555 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5556
5557 // Window should receive motion event.
5558 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5559
5560 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005561 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005562
5563 // The first window gets cancel.
5564 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5565 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5566
5567 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005568 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005569 SECOND_DISPLAY_ID, {150, 50}))
5570 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5571 firstWindowInPrimary->assertNoEvents();
5572 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5573
5574 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005575 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005576 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5577 firstWindowInPrimary->assertNoEvents();
5578 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5579}
5580
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005581TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005582 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005583 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5584 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005585
Vishnu Nair47074b82020-08-14 11:54:47 -07005586 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005587 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005588 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005589
5590 window->consumeFocusEvent(true);
5591
Prabir Pradhan678438e2023-04-13 19:32:51 +00005592 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005593
5594 // Window should receive key down event.
5595 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005596
5597 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005598 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005599 mFakePolicy->assertUserActivityPoked();
5600}
5601
5602TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5603 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5604 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5605 "Fake Window", ADISPLAY_ID_DEFAULT);
5606
5607 window->setDisableUserActivity(true);
5608 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005609 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005610 setFocusedWindow(window);
5611
5612 window->consumeFocusEvent(true);
5613
5614 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5615
5616 // Window should receive key down event.
5617 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5618
5619 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005620 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005621 mFakePolicy->assertUserActivityNotPoked();
5622}
5623
5624TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5625 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5626 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5627 "Fake Window", ADISPLAY_ID_DEFAULT);
5628
5629 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005630 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005631 setFocusedWindow(window);
5632
5633 window->consumeFocusEvent(true);
5634
5635 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5636 mDispatcher->waitForIdle();
5637
5638 // System key is not passed down
5639 window->assertNoEvents();
5640
5641 // Should have poked user activity
5642 mFakePolicy->assertUserActivityPoked();
5643}
5644
5645TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5646 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5647 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5648 "Fake Window", ADISPLAY_ID_DEFAULT);
5649
5650 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005651 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005652 setFocusedWindow(window);
5653
5654 window->consumeFocusEvent(true);
5655
5656 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5657 mDispatcher->waitForIdle();
5658
5659 // System key is not passed down
5660 window->assertNoEvents();
5661
5662 // Should have poked user activity
5663 mFakePolicy->assertUserActivityPoked();
5664}
5665
5666TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5667 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5668 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5669 "Fake Window", ADISPLAY_ID_DEFAULT);
5670
5671 window->setDisableUserActivity(true);
5672 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005673 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005674 setFocusedWindow(window);
5675
5676 window->consumeFocusEvent(true);
5677
5678 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5679 mDispatcher->waitForIdle();
5680
5681 // System key is not passed down
5682 window->assertNoEvents();
5683
5684 // Should have poked user activity
5685 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005686}
5687
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005688TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5689 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5690 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5691 "Fake Window", ADISPLAY_ID_DEFAULT);
5692
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005693 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005694
5695 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005696 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005697 ADISPLAY_ID_DEFAULT, {100, 100}))
5698 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5699
5700 window->consumeMotionEvent(
5701 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5702
5703 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005704 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005705 mFakePolicy->assertUserActivityPoked();
5706}
5707
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005708TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005709 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005710 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5711 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005712
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005713 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005714
Prabir Pradhan678438e2023-04-13 19:32:51 +00005715 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005716 mDispatcher->waitForIdle();
5717
5718 window->assertNoEvents();
5719}
5720
5721// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5722TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005723 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005724 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5725 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005726
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005727 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005728
5729 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005730 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005731 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005732 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5733 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005734
5735 // Window should receive only the motion event
5736 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5737 window->assertNoEvents(); // Key event or focus event will not be received
5738}
5739
arthurhungea3f4fc2020-12-21 23:18:53 +08005740TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5741 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5742
arthurhungea3f4fc2020-12-21 23:18:53 +08005743 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005744 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5745 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005746 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005747
arthurhungea3f4fc2020-12-21 23:18:53 +08005748 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005749 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5750 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005751 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005752
5753 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005754 mDispatcher->onWindowInfosChanged(
5755 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005756
5757 PointF pointInFirst = {300, 200};
5758 PointF pointInSecond = {300, 600};
5759
5760 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005761 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5762 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5763 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005764 // Only the first window should get the down event
5765 firstWindow->consumeMotionDown();
5766 secondWindow->assertNoEvents();
5767
5768 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005769 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5770 ADISPLAY_ID_DEFAULT,
5771 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005772 // The first window gets a move and the second a down
5773 firstWindow->consumeMotionMove();
5774 secondWindow->consumeMotionDown();
5775
5776 // Send pointer cancel to the second window
5777 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005778 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005779 {pointInFirst, pointInSecond});
5780 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005781 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005782 // The first window gets move and the second gets cancel.
5783 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5784 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5785
5786 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005787 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5788 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005789 // The first window gets up and the second gets nothing.
5790 firstWindow->consumeMotionUp();
5791 secondWindow->assertNoEvents();
5792}
5793
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005794TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5795 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5796
5797 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005798 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005799 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005800 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5801 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5802 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5803
Harry Cutts33476232023-01-30 19:57:29 +00005804 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005805 window->assertNoEvents();
5806 mDispatcher->waitForIdle();
5807}
5808
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005809using InputDispatcherMonitorTest = InputDispatcherTest;
5810
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005811/**
5812 * Two entities that receive touch: A window, and a global monitor.
5813 * The touch goes to the window, and then the window disappears.
5814 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5815 * for the monitor, as well.
5816 * 1. foregroundWindow
5817 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5818 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005819TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005820 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5821 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005822 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005823
Prabir Pradhanfb549072023-10-05 19:17:36 +00005824 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005825
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005826 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005827 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005828 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005829 {100, 200}))
5830 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5831
5832 // Both the foreground window and the global monitor should receive the touch down
5833 window->consumeMotionDown();
5834 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5835
5836 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005837 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005838 ADISPLAY_ID_DEFAULT, {110, 200}))
5839 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5840
5841 window->consumeMotionMove();
5842 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5843
5844 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005845 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005846 window->consumeMotionCancel();
5847 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5848
5849 // If more events come in, there will be no more foreground window to send them to. This will
5850 // cause a cancel for the monitor, as well.
5851 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005852 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005853 ADISPLAY_ID_DEFAULT, {120, 200}))
5854 << "Injection should fail because the window was removed";
5855 window->assertNoEvents();
5856 // Global monitor now gets the cancel
5857 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5858}
5859
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005860TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005861 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005862 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5863 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005864 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005865
Prabir Pradhanfb549072023-10-05 19:17:36 +00005866 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005867
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005868 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005869 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005870 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005871 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005872 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005873}
5874
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005875TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00005876 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005877
Chris Yea209fde2020-07-22 13:54:51 -07005878 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005879 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5880 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005881 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005882
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005883 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005884 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005885 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005886 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005887 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005888
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005889 // Pilfer pointers from the monitor.
5890 // This should not do anything and the window should continue to receive events.
5891 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005892
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005893 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005894 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005895 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005896 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005897
5898 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5899 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005900}
5901
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005902TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005903 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005904 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5905 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005906 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07005907 window->setWindowOffset(20, 40);
5908 window->setWindowTransform(0, 1, -1, 0);
5909
Prabir Pradhanfb549072023-10-05 19:17:36 +00005910 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005911
5912 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005913 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07005914 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5915 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5916 MotionEvent* event = monitor.consumeMotion();
5917 // Even though window has transform, gesture monitor must not.
5918 ASSERT_EQ(ui::Transform(), event->getTransform());
5919}
5920
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005921TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005922 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00005923 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005924
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005925 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005926 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005927 << "Injection should fail if there is a monitor, but no touchable window";
5928 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005929}
5930
chaviw81e2bb92019-12-18 15:03:51 -08005931TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005932 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005933 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5934 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005935
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005936 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08005937
5938 NotifyMotionArgs motionArgs =
5939 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5940 ADISPLAY_ID_DEFAULT);
5941
Prabir Pradhan678438e2023-04-13 19:32:51 +00005942 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005943 // Window should receive motion down event.
5944 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5945
5946 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005947 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005948 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5949 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5950 motionArgs.pointerCoords[0].getX() - 10);
5951
Prabir Pradhan678438e2023-04-13 19:32:51 +00005952 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00005953 window->consumeMotionMove(ADISPLAY_ID_DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005954}
5955
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005956/**
5957 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5958 * the device default right away. In the test scenario, we check both the default value,
5959 * and the action of enabling / disabling.
5960 */
5961TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005962 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005963 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5964 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005965 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005966
5967 // Set focused application.
5968 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005969 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005970
5971 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005972 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005973 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005974 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005975
5976 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005977 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005978 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005979 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005980
5981 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005982 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005983 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005984 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005985 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005986 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005987 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005988 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005989
5990 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005991 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005992 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005993 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005994
5995 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005996 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005997 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005998 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005999 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006000 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006001 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006002 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006003
6004 window->assertNoEvents();
6005}
6006
Gang Wange9087892020-01-07 12:17:14 -05006007TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006008 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006009 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6010 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05006011
6012 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006013 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05006014
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006015 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006016 setFocusedWindow(window);
6017
Harry Cutts33476232023-01-30 19:57:29 +00006018 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05006019
Prabir Pradhan678438e2023-04-13 19:32:51 +00006020 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
6021 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05006022
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006023 const KeyEvent& event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05006024
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006025 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(event);
Gang Wange9087892020-01-07 12:17:14 -05006026 ASSERT_NE(verified, nullptr);
6027 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
6028
6029 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
6030 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
6031 ASSERT_EQ(keyArgs.source, verified->source);
6032 ASSERT_EQ(keyArgs.displayId, verified->displayId);
6033
6034 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
6035
6036 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05006037 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006038 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05006039 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
6040 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
6041 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
6042 ASSERT_EQ(0, verifiedKey.repeatCount);
6043}
6044
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006045TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006046 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006047 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6048 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006049
6050 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6051
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006052 ui::Transform transform;
6053 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6054
6055 gui::DisplayInfo displayInfo;
6056 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6057 displayInfo.transform = transform;
6058
Patrick Williamsd828f302023-04-28 17:52:08 -05006059 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006060
Prabir Pradhan678438e2023-04-13 19:32:51 +00006061 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006062 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6063 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006064 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006065
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006066 const MotionEvent& event = window->consumeMotionEvent();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006067
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006068 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006069 ASSERT_NE(verified, nullptr);
6070 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
6071
6072 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
6073 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
6074 EXPECT_EQ(motionArgs.source, verified->source);
6075 EXPECT_EQ(motionArgs.displayId, verified->displayId);
6076
6077 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
6078
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006079 const vec2 rawXY =
6080 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
6081 motionArgs.pointerCoords[0].getXYValue());
6082 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
6083 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006084 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006085 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006086 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006087 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
6088 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
6089}
6090
chaviw09c8d2d2020-08-24 15:48:26 -07006091/**
6092 * Ensure that separate calls to sign the same data are generating the same key.
6093 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
6094 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
6095 * tests.
6096 */
6097TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
6098 KeyEvent event = getTestKeyEvent();
6099 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6100
6101 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
6102 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
6103 ASSERT_EQ(hmac1, hmac2);
6104}
6105
6106/**
6107 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6108 */
6109TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6110 KeyEvent event = getTestKeyEvent();
6111 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6112 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6113
6114 verifiedEvent.deviceId += 1;
6115 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6116
6117 verifiedEvent.source += 1;
6118 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6119
6120 verifiedEvent.eventTimeNanos += 1;
6121 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6122
6123 verifiedEvent.displayId += 1;
6124 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6125
6126 verifiedEvent.action += 1;
6127 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6128
6129 verifiedEvent.downTimeNanos += 1;
6130 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6131
6132 verifiedEvent.flags += 1;
6133 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6134
6135 verifiedEvent.keyCode += 1;
6136 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6137
6138 verifiedEvent.scanCode += 1;
6139 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6140
6141 verifiedEvent.metaState += 1;
6142 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6143
6144 verifiedEvent.repeatCount += 1;
6145 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6146}
6147
Vishnu Nair958da932020-08-21 17:12:37 -07006148TEST_F(InputDispatcherTest, SetFocusedWindow) {
6149 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6150 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006151 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006152 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006153 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006154 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6155
6156 // Top window is also focusable but is not granted focus.
6157 windowTop->setFocusable(true);
6158 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006159 mDispatcher->onWindowInfosChanged(
6160 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006161 setFocusedWindow(windowSecond);
6162
6163 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006164 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006165 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006166
6167 // Focused window should receive event.
6168 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6169 windowTop->assertNoEvents();
6170}
6171
6172TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
6173 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6174 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006175 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006176 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6177
6178 window->setFocusable(true);
6179 // Release channel for window is no longer valid.
6180 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006181 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006182 setFocusedWindow(window);
6183
6184 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006185 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006186
6187 // window channel is invalid, so it should not receive any input event.
6188 window->assertNoEvents();
6189}
6190
6191TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
6192 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6193 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006194 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006195 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006196 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6197
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006198 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006199 setFocusedWindow(window);
6200
6201 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006202 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006203
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006204 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006205 window->assertNoEvents();
6206}
6207
6208TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6209 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6210 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006211 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006212 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006213 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006214 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6215
6216 windowTop->setFocusable(true);
6217 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006218 mDispatcher->onWindowInfosChanged(
6219 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006220 setFocusedWindow(windowTop);
6221 windowTop->consumeFocusEvent(true);
6222
Chavi Weingarten847e8512023-03-29 00:26:09 +00006223 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006224 mDispatcher->onWindowInfosChanged(
6225 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006226 windowSecond->consumeFocusEvent(true);
6227 windowTop->consumeFocusEvent(false);
6228
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006229 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006230 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006231
6232 // Focused window should receive event.
6233 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6234}
6235
Chavi Weingarten847e8512023-03-29 00:26:09 +00006236TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006237 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6238 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006239 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006240 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006241 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006242 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6243
6244 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006245 windowSecond->setFocusable(false);
6246 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006247 mDispatcher->onWindowInfosChanged(
6248 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006249 setFocusedWindow(windowTop);
6250 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006251
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006252 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006253 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006254
6255 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006256 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006257 windowSecond->assertNoEvents();
6258}
6259
6260TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6261 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6262 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006263 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006264 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006265 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6266 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006267 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6268
6269 window->setFocusable(true);
6270 previousFocusedWindow->setFocusable(true);
6271 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006272 mDispatcher->onWindowInfosChanged(
6273 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006274 setFocusedWindow(previousFocusedWindow);
6275 previousFocusedWindow->consumeFocusEvent(true);
6276
6277 // Requesting focus on invisible window takes focus from currently focused window.
6278 setFocusedWindow(window);
6279 previousFocusedWindow->consumeFocusEvent(false);
6280
6281 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006282 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006283 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6284 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006285
6286 // Window does not get focus event or key down.
6287 window->assertNoEvents();
6288
6289 // Window becomes visible.
6290 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006291 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006292
6293 // Window receives focus event.
6294 window->consumeFocusEvent(true);
6295 // Focused window receives key down.
6296 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6297}
6298
Vishnu Nair599f1412021-06-21 10:39:58 -07006299TEST_F(InputDispatcherTest, DisplayRemoved) {
6300 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6301 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006302 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006303 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6304
6305 // window is granted focus.
6306 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006307 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006308 setFocusedWindow(window);
6309 window->consumeFocusEvent(true);
6310
6311 // When a display is removed window loses focus.
6312 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6313 window->consumeFocusEvent(false);
6314}
6315
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006316/**
6317 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6318 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6319 * of the 'slipperyEnterWindow'.
6320 *
6321 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6322 * a way so that the touched location is no longer covered by the top window.
6323 *
6324 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6325 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6326 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6327 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6328 * with ACTION_DOWN).
6329 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6330 * window moved itself away from the touched location and had Flag::SLIPPERY.
6331 *
6332 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6333 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6334 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6335 *
6336 * In this test, we ensure that the event received by the bottom window has
6337 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6338 */
6339TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006340 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006341 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006342
6343 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6344 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6345
6346 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006347 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006348 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006349 // Make sure this one overlaps the bottom window
6350 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6351 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6352 // one. Windows with the same owner are not considered to be occluding each other.
6353 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6354
6355 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006356 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006357 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6358
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006359 mDispatcher->onWindowInfosChanged(
6360 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006361
6362 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006363 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6364 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6365 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006366 slipperyExitWindow->consumeMotionDown();
6367 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006368 mDispatcher->onWindowInfosChanged(
6369 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006370
Prabir Pradhan678438e2023-04-13 19:32:51 +00006371 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6372 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6373 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006374
6375 slipperyExitWindow->consumeMotionCancel();
6376
6377 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6378 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6379}
6380
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006381/**
6382 * Two windows, one on the left and another on the right. The left window is slippery. The right
6383 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6384 * touch moves from the left window into the right window, the gesture should continue to go to the
6385 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6386 * reproduces a crash.
6387 */
6388TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6389 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6390
6391 sp<FakeWindowHandle> leftSlipperyWindow =
6392 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6393 leftSlipperyWindow->setSlippery(true);
6394 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6395
6396 sp<FakeWindowHandle> rightDropTouchesWindow =
6397 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6398 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6399 rightDropTouchesWindow->setDropInput(true);
6400
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006401 mDispatcher->onWindowInfosChanged(
6402 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006403
6404 // Start touch in the left window
6405 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6406 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6407 .build());
6408 leftSlipperyWindow->consumeMotionDown();
6409
6410 // And move it into the right window
6411 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6412 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6413 .build());
6414
6415 // Since the right window isn't eligible to receive input, touch does not slip.
6416 // The left window continues to receive the gesture.
6417 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6418 rightDropTouchesWindow->assertNoEvents();
6419}
6420
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006421/**
6422 * A single window is on screen first. Touch is injected into that window. Next, a second window
6423 * appears. Since the first window is slippery, touch will move from the first window to the second.
6424 */
6425TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6426 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6427 sp<FakeWindowHandle> originalWindow =
6428 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6429 originalWindow->setFrame(Rect(0, 0, 200, 200));
6430 originalWindow->setSlippery(true);
6431
6432 sp<FakeWindowHandle> appearingWindow =
6433 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6434 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6435
6436 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6437
6438 // Touch down on the original window
6439 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6440 injectMotionEvent(*mDispatcher,
6441 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6442 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6443 .build()));
6444 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6445
6446 // Now, a new window appears. This could be, for example, a notification shade that appears
6447 // after user starts to drag down on the launcher window.
6448 mDispatcher->onWindowInfosChanged(
6449 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6450 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6451 injectMotionEvent(*mDispatcher,
6452 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6453 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6454 .build()));
6455 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6456 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6457 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6458 injectMotionEvent(*mDispatcher,
6459 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6460 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6461 .build()));
6462 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6463
6464 originalWindow->assertNoEvents();
6465 appearingWindow->assertNoEvents();
6466}
6467
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006468TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006469 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006470 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6471
6472 sp<FakeWindowHandle> leftWindow =
6473 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6474 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006475 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006476
6477 sp<FakeWindowHandle> rightSpy =
6478 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6479 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006480 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006481 rightSpy->setSpy(true);
6482 rightSpy->setTrustedOverlay(true);
6483
6484 sp<FakeWindowHandle> rightWindow =
6485 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6486 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006487 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006488
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006489 mDispatcher->onWindowInfosChanged(
6490 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006491
6492 // Touch in the left window
6493 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6494 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6495 .build());
6496 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6497 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006498 ASSERT_NO_FATAL_FAILURE(
6499 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006500
6501 // Touch another finger over the right windows
6502 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6503 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6504 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6505 .build());
6506 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6507 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6508 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6509 mDispatcher->waitForIdle();
6510 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006511 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6512 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006513
6514 // Release finger over left window. The UP actions are not treated as device interaction.
6515 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6516 // is part of the UP action, we do not treat this as device interaction.
6517 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6518 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6519 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6520 .build());
6521 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6522 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6523 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6524 mDispatcher->waitForIdle();
6525 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6526
6527 // Move remaining finger
6528 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6529 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6530 .build());
6531 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6532 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6533 mDispatcher->waitForIdle();
6534 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006535 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006536
6537 // Release all fingers
6538 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6539 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6540 .build());
6541 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6542 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6543 mDispatcher->waitForIdle();
6544 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6545}
6546
6547TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6548 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6549
6550 sp<FakeWindowHandle> window =
6551 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6552 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006553 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006554
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006555 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006556 setFocusedWindow(window);
6557 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6558
6559 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6560 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6561 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006562 ASSERT_NO_FATAL_FAILURE(
6563 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006564
6565 // The UP actions are not treated as device interaction.
6566 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6567 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6568 mDispatcher->waitForIdle();
6569 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6570}
6571
Prabir Pradhan5893d362023-11-17 04:30:40 +00006572TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
6573 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6574
6575 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
6576 ADISPLAY_ID_DEFAULT);
6577 left->setFrame(Rect(0, 0, 100, 100));
6578 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
6579 "Right Window", ADISPLAY_ID_DEFAULT);
6580 right->setFrame(Rect(100, 0, 200, 100));
6581 sp<FakeWindowHandle> spy =
6582 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
6583 spy->setFrame(Rect(0, 0, 200, 100));
6584 spy->setTrustedOverlay(true);
6585 spy->setSpy(true);
6586
6587 mDispatcher->onWindowInfosChanged(
6588 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
6589
6590 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
6591 NotifyMotionArgs notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
6592 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
6593 mDispatcher->notifyMotion(notifyArgs);
6594
6595 const MotionEvent& leftEnter = left->consumeMotionEvent(
6596 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
6597 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6598
6599 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6600 Not(WithEventId(notifyArgs.id)),
6601 Not(WithEventId(leftEnter.getId())),
6602 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6603
6604 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
6605 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
6606 {PointF{150, 50}});
6607 mDispatcher->notifyMotion(notifyArgs);
6608
6609 const MotionEvent& leftExit = left->consumeMotionEvent(
6610 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
6611 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6612
6613 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6614 Not(WithEventId(notifyArgs.id)),
6615 Not(WithEventId(leftExit.getId())),
6616 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6617
6618 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
6619}
6620
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00006621class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
6622protected:
6623 std::shared_ptr<FakeApplicationHandle> mApp;
6624 sp<FakeWindowHandle> mWindow;
6625
6626 virtual void SetUp() override {
6627 InputDispatcherTest::SetUp();
6628
6629 mApp = std::make_shared<FakeApplicationHandle>();
6630
6631 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6632 mWindow->setFrame(Rect(0, 0, 100, 100));
6633
6634 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
6635 setFocusedWindow(mWindow);
6636 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
6637 }
6638
6639 void setFallback(int32_t keycode) {
6640 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
6641 return KeyEventBuilder(event).keyCode(keycode).build();
6642 });
6643 }
6644
6645 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006646 const KeyEvent& event = mWindow->consumeKey(handled);
6647 ASSERT_THAT(event, matcher);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00006648 }
6649};
6650
6651TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
6652 mDispatcher->notifyKey(
6653 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6654 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6655 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6656}
6657
6658TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
6659 mDispatcher->notifyKey(
6660 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6661 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6662 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6663}
6664
6665TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
6666 mDispatcher->notifyKey(
6667 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6668
6669 // Do not handle this key event.
6670 consumeKey(/*handled=*/false,
6671 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6672 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6673
6674 // Since the policy did not request any fallback to be generated, ensure there are no events.
6675 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6676}
6677
6678TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
6679 setFallback(AKEYCODE_B);
6680 mDispatcher->notifyKey(
6681 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6682
6683 // Do not handle this key event.
6684 consumeKey(/*handled=*/false,
6685 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6686
6687 // Since the key was not handled, ensure the fallback event was dispatched instead.
6688 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6689 consumeKey(/*handled=*/true,
6690 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6691 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6692
6693 // Release the original key, and ensure the fallback key is also released.
6694 mDispatcher->notifyKey(
6695 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6696 consumeKey(/*handled=*/false,
6697 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6698 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6699 consumeKey(/*handled=*/true,
6700 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6701 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6702
6703 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6704 mWindow->assertNoEvents();
6705}
6706
6707TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
6708 setFallback(AKEYCODE_B);
6709 mDispatcher->notifyKey(
6710 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6711
6712 // Do not handle this key event, but handle the fallback.
6713 consumeKey(/*handled=*/false,
6714 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6715 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6716 consumeKey(/*handled=*/true,
6717 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6718 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6719
6720 // Release the original key, and ensure the fallback key is also released.
6721 mDispatcher->notifyKey(
6722 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6723 // But this time, the app handles the original key.
6724 consumeKey(/*handled=*/true,
6725 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6726 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6727 // Ensure the fallback key is canceled.
6728 consumeKey(/*handled=*/true,
6729 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6730 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6731
6732 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6733 mWindow->assertNoEvents();
6734}
6735
6736TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
6737 setFallback(AKEYCODE_B);
6738 mDispatcher->notifyKey(
6739 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6740
6741 // Do not handle this key event.
6742 consumeKey(/*handled=*/false,
6743 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6744 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6745 // App does not handle the fallback either, so ensure another fallback is not generated.
6746 setFallback(AKEYCODE_C);
6747 consumeKey(/*handled=*/false,
6748 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6749 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6750
6751 // Release the original key, and ensure the fallback key is also released.
6752 setFallback(AKEYCODE_B);
6753 mDispatcher->notifyKey(
6754 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6755 consumeKey(/*handled=*/false,
6756 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6757 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6758 consumeKey(/*handled=*/false,
6759 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6760 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6761
6762 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6763 mWindow->assertNoEvents();
6764}
6765
6766TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
6767 setFallback(AKEYCODE_B);
6768 mDispatcher->notifyKey(
6769 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6770
6771 // Do not handle this key event, so fallback is generated.
6772 consumeKey(/*handled=*/false,
6773 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6774 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6775 consumeKey(/*handled=*/true,
6776 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6777 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6778
6779 // Release the original key, but assume the policy is misbehaving and it
6780 // generates an inconsistent fallback to the one from the DOWN event.
6781 setFallback(AKEYCODE_C);
6782 mDispatcher->notifyKey(
6783 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6784 consumeKey(/*handled=*/false,
6785 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6786 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6787 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
6788 consumeKey(/*handled=*/true,
6789 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6790 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6791
6792 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6793 mWindow->assertNoEvents();
6794}
6795
6796TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
6797 setFallback(AKEYCODE_B);
6798 mDispatcher->notifyKey(
6799 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6800
6801 // Do not handle this key event, so fallback is generated.
6802 consumeKey(/*handled=*/false,
6803 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6804 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6805 consumeKey(/*handled=*/true,
6806 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6807 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6808
6809 // The original key is canceled.
6810 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
6811 .keyCode(AKEYCODE_A)
6812 .addFlag(AKEY_EVENT_FLAG_CANCELED)
6813 .build());
6814 consumeKey(/*handled=*/false,
6815 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
6816 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
6817 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6818 // Ensure the fallback key is also canceled due to the original key being canceled.
6819 consumeKey(/*handled=*/true,
6820 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6821 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6822
6823 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6824 mWindow->assertNoEvents();
6825}
6826
Garfield Tan1c7bc862020-01-28 13:24:04 -08006827class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
6828protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08006829 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
6830 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006831
Chris Yea209fde2020-07-22 13:54:51 -07006832 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006833 sp<FakeWindowHandle> mWindow;
6834
6835 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00006836 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00006837 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00006838 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09006839 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006840 ASSERT_EQ(OK, mDispatcher->start());
6841
6842 setUpWindow();
6843 }
6844
6845 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07006846 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006847 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006848
Vishnu Nair47074b82020-08-14 11:54:47 -07006849 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006850 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006851 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006852 mWindow->consumeFocusEvent(true);
6853 }
6854
Chris Ye2ad95392020-09-01 13:44:44 -07006855 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006856 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006857 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006858 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006859 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006860
6861 // Window should receive key down event.
6862 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6863 }
6864
6865 void expectKeyRepeatOnce(int32_t repeatCount) {
6866 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006867 mWindow->consumeKeyEvent(
6868 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08006869 }
6870
Chris Ye2ad95392020-09-01 13:44:44 -07006871 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006872 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006873 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006874 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006875 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006876
6877 // Window should receive key down event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006878 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00006879 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006880 }
6881};
6882
6883TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00006884 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006885 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6886 expectKeyRepeatOnce(repeatCount);
6887 }
6888}
6889
6890TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00006891 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006892 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6893 expectKeyRepeatOnce(repeatCount);
6894 }
Harry Cutts33476232023-01-30 19:57:29 +00006895 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006896 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08006897 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6898 expectKeyRepeatOnce(repeatCount);
6899 }
6900}
6901
6902TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006903 sendAndConsumeKeyDown(/*deviceId=*/1);
6904 expectKeyRepeatOnce(/*repeatCount=*/1);
6905 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006906 mWindow->assertNoEvents();
6907}
6908
6909TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006910 sendAndConsumeKeyDown(/*deviceId=*/1);
6911 expectKeyRepeatOnce(/*repeatCount=*/1);
6912 sendAndConsumeKeyDown(/*deviceId=*/2);
6913 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006914 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00006915 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006916 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00006917 expectKeyRepeatOnce(/*repeatCount=*/2);
6918 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07006919 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00006920 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006921 mWindow->assertNoEvents();
6922}
6923
6924TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006925 sendAndConsumeKeyDown(/*deviceId=*/1);
6926 expectKeyRepeatOnce(/*repeatCount=*/1);
6927 sendAndConsumeKeyDown(/*deviceId=*/2);
6928 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006929 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00006930 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006931 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08006932 mWindow->assertNoEvents();
6933}
6934
liushenxiang42232912021-05-21 20:24:09 +08006935TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
6936 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00006937 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006938 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08006939 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
6940 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
6941 mWindow->assertNoEvents();
6942}
6943
Garfield Tan1c7bc862020-01-28 13:24:04 -08006944TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006945 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006946 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006947 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006948 const KeyEvent& repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006949 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006950 IdGenerator::getSource(repeatEvent.getId()));
Garfield Tan1c7bc862020-01-28 13:24:04 -08006951 }
6952}
6953
6954TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006955 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006956 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006957
6958 std::unordered_set<int32_t> idSet;
6959 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006960 const KeyEvent& repeatEvent = mWindow->consumeKey();
6961 int32_t id = repeatEvent.getId();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006962 EXPECT_EQ(idSet.end(), idSet.find(id));
6963 idSet.insert(id);
6964 }
6965}
6966
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006967/* Test InputDispatcher for MultiDisplay */
6968class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
6969public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006970 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006971 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08006972
Chris Yea209fde2020-07-22 13:54:51 -07006973 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006974 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006975 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006976
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006977 // Set focus window for primary display, but focused display would be second one.
6978 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07006979 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006980 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
6981
Vishnu Nair958da932020-08-21 17:12:37 -07006982 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006983 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08006984
Chris Yea209fde2020-07-22 13:54:51 -07006985 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006986 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006987 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006988 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006989 // Set focus display to second one.
6990 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
6991 // Set focus window for second display.
6992 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07006993 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006994 mDispatcher->onWindowInfosChanged(
6995 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006996 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006997 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006998 }
6999
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007000 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007001 InputDispatcherTest::TearDown();
7002
Chris Yea209fde2020-07-22 13:54:51 -07007003 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007004 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07007005 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007006 windowInSecondary.clear();
7007 }
7008
7009protected:
Chris Yea209fde2020-07-22 13:54:51 -07007010 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007011 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07007012 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007013 sp<FakeWindowHandle> windowInSecondary;
7014};
7015
7016TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
7017 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007018 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007019 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007020 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007021 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08007022 windowInSecondary->assertNoEvents();
7023
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007024 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007025 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007026 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007027 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007028 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007029 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08007030}
7031
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007032TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08007033 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007034 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007035 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007036 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007037 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08007038 windowInSecondary->assertNoEvents();
7039
7040 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007041 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007042 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007043 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007044 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08007045
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007046 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007047 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08007048
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007049 // Old focus should receive a cancel event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007050 windowInSecondary->consumeKeyUp(ADISPLAY_ID_NONE, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08007051
7052 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007053 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08007054 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007055 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08007056 windowInSecondary->assertNoEvents();
7057}
7058
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007059// Test per-display input monitors for motion event.
7060TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08007061 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007062 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007063 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007064 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007065
7066 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007067 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007068 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007069 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007070 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007071 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007072 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007073 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007074
7075 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007076 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007077 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007078 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007079 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007080 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007081 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08007082 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007083
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007084 // Lift up the touch from the second display
7085 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007086 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007087 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7088 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
7089 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
7090
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007091 // Test inject a non-pointer motion event.
7092 // If specific a display, it will dispatch to the focused window of particular display,
7093 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007094 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007095 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007096 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007097 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007098 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007099 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007100 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007101}
7102
7103// Test per-display input monitors for key event.
7104TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007105 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08007106 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007107 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007108 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007109 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007110
7111 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007112 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007113 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007114 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007115 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007116 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007117 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007118}
7119
Vishnu Nair958da932020-08-21 17:12:37 -07007120TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
7121 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007122 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007123 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007124 mDispatcher->onWindowInfosChanged(
7125 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
7126 *windowInSecondary->getInfo()},
7127 {},
7128 0,
7129 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007130 setFocusedWindow(secondWindowInPrimary);
7131 windowInPrimary->consumeFocusEvent(false);
7132 secondWindowInPrimary->consumeFocusEvent(true);
7133
7134 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007135 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7136 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007137 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007138 windowInPrimary->assertNoEvents();
7139 windowInSecondary->assertNoEvents();
7140 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7141}
7142
Arthur Hungdfd528e2021-12-08 13:23:04 +00007143TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
7144 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007145 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007146 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007147 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007148
7149 // Test touch down on primary display.
7150 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007151 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007152 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7153 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7154 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
7155
7156 // Test touch down on second display.
7157 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007158 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007159 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7160 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
7161 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
7162
7163 // Trigger cancel touch.
7164 mDispatcher->cancelCurrentTouch();
7165 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7166 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7167 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
7168 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
7169
7170 // Test inject a move motion event, no window/monitor should receive the event.
7171 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007172 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007173 ADISPLAY_ID_DEFAULT, {110, 200}))
7174 << "Inject motion event should return InputEventInjectionResult::FAILED";
7175 windowInPrimary->assertNoEvents();
7176 monitorInPrimary.assertNoEvents();
7177
7178 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007179 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007180 SECOND_DISPLAY_ID, {110, 200}))
7181 << "Inject motion event should return InputEventInjectionResult::FAILED";
7182 windowInSecondary->assertNoEvents();
7183 monitorInSecondary.assertNoEvents();
7184}
7185
Jackal Guof9696682018-10-05 12:23:23 +08007186class InputFilterTest : public InputDispatcherTest {
7187protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007188 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
7189 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08007190 NotifyMotionArgs motionArgs;
7191
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007192 motionArgs =
7193 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007194 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007195 motionArgs =
7196 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007197 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007198 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007199 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007200 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007201 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08007202 } else {
7203 mFakePolicy->assertFilterInputEventWasNotCalled();
7204 }
7205 }
7206
7207 void testNotifyKey(bool expectToBeFiltered) {
7208 NotifyKeyArgs keyArgs;
7209
7210 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007211 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007212 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007213 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007214 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007215
7216 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08007217 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007218 } else {
7219 mFakePolicy->assertFilterInputEventWasNotCalled();
7220 }
7221 }
7222};
7223
7224// Test InputFilter for MotionEvent
7225TEST_F(InputFilterTest, MotionEvent_InputFilter) {
7226 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007227 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7228 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007229
7230 // Enable InputFilter
7231 mDispatcher->setInputFilterEnabled(true);
7232 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007233 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
7234 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007235
7236 // Disable InputFilter
7237 mDispatcher->setInputFilterEnabled(false);
7238 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007239 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7240 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007241}
7242
7243// Test InputFilter for KeyEvent
7244TEST_F(InputFilterTest, KeyEvent_InputFilter) {
7245 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007246 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007247
7248 // Enable InputFilter
7249 mDispatcher->setInputFilterEnabled(true);
7250 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007251 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007252
7253 // Disable InputFilter
7254 mDispatcher->setInputFilterEnabled(false);
7255 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007256 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007257}
7258
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007259// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
7260// logical display coordinate space.
7261TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
7262 ui::Transform firstDisplayTransform;
7263 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7264 ui::Transform secondDisplayTransform;
7265 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
7266
7267 std::vector<gui::DisplayInfo> displayInfos(2);
7268 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
7269 displayInfos[0].transform = firstDisplayTransform;
7270 displayInfos[1].displayId = SECOND_DISPLAY_ID;
7271 displayInfos[1].transform = secondDisplayTransform;
7272
Patrick Williamsd828f302023-04-28 17:52:08 -05007273 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007274
7275 // Enable InputFilter
7276 mDispatcher->setInputFilterEnabled(true);
7277
7278 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007279 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
7280 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007281}
7282
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007283class InputFilterInjectionPolicyTest : public InputDispatcherTest {
7284protected:
7285 virtual void SetUp() override {
7286 InputDispatcherTest::SetUp();
7287
7288 /**
7289 * We don't need to enable input filter to test the injected event policy, but we enabled it
7290 * here to make the tests more realistic, since this policy only matters when inputfilter is
7291 * on.
7292 */
7293 mDispatcher->setInputFilterEnabled(true);
7294
7295 std::shared_ptr<InputApplicationHandle> application =
7296 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007297 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
7298 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007299
7300 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7301 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007302 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007303 setFocusedWindow(mWindow);
7304 mWindow->consumeFocusEvent(true);
7305 }
7306
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007307 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7308 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007309 KeyEvent event;
7310
7311 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7312 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
7313 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00007314 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007315 const int32_t additionalPolicyFlags =
7316 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
7317 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007318 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007319 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007320 policyFlags | additionalPolicyFlags));
7321
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007322 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007323 }
7324
7325 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7326 int32_t flags) {
7327 MotionEvent event;
7328 PointerProperties pointerProperties[1];
7329 PointerCoords pointerCoords[1];
7330 pointerProperties[0].clear();
7331 pointerProperties[0].id = 0;
7332 pointerCoords[0].clear();
7333 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
7334 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
7335
7336 ui::Transform identityTransform;
7337 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7338 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
7339 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
7340 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
7341 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07007342 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07007343 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007344 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007345
7346 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
7347 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007348 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007349 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007350 policyFlags | additionalPolicyFlags));
7351
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007352 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007353 }
7354
7355private:
7356 sp<FakeWindowHandle> mWindow;
7357};
7358
7359TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007360 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
7361 // filter. Without it, the event will no different from a regularly injected event, and the
7362 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00007363 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
7364 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007365}
7366
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007367TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007368 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007369 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007370 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
7371}
7372
7373TEST_F(InputFilterInjectionPolicyTest,
7374 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
7375 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007376 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007377 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007378}
7379
7380TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00007381 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
7382 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007383}
7384
chaviwfd6d3512019-03-25 13:23:49 -07007385class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007386 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07007387 InputDispatcherTest::SetUp();
7388
Chris Yea209fde2020-07-22 13:54:51 -07007389 std::shared_ptr<FakeApplicationHandle> application =
7390 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007391 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007392 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007393 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07007394
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007395 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007396 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007397 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07007398
7399 // Set focused application.
7400 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007401 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07007402
7403 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007404 mDispatcher->onWindowInfosChanged(
7405 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007406 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007407 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07007408 }
7409
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007410 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07007411 InputDispatcherTest::TearDown();
7412
7413 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007414 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07007415 }
7416
7417protected:
7418 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007419 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007420 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07007421};
7422
7423// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7424// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
7425// the onPointerDownOutsideFocus callback.
7426TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007427 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007428 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007429 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007430 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007431 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007432
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007433 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07007434 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
7435}
7436
7437// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
7438// DOWN on the window that doesn't have focus. Ensure no window received the
7439// onPointerDownOutsideFocus callback.
7440TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007441 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007442 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
7443 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007444 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007445 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007446
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007447 ASSERT_TRUE(mDispatcher->waitForIdle());
7448 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007449}
7450
7451// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
7452// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
7453TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007454 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007455 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007456 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007457 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007458
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007459 ASSERT_TRUE(mDispatcher->waitForIdle());
7460 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007461}
7462
7463// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7464// DOWN on the window that already has focus. Ensure no window received the
7465// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007466TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007467 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007468 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007469 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007470 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007471 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007472
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007473 ASSERT_TRUE(mDispatcher->waitForIdle());
7474 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007475}
7476
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007477// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
7478// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
7479TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
7480 const MotionEvent event =
7481 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
7482 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007483 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007484 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
7485 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007486 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007487 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7488 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7489
7490 ASSERT_TRUE(mDispatcher->waitForIdle());
7491 mFakePolicy->assertOnPointerDownWasNotCalled();
7492 // Ensure that the unfocused window did not receive any FOCUS events.
7493 mUnfocusedWindow->assertNoEvents();
7494}
7495
chaviwaf87b3e2019-10-01 16:59:28 -07007496// These tests ensures we can send touch events to a single client when there are multiple input
7497// windows that point to the same client token.
7498class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
7499 virtual void SetUp() override {
7500 InputDispatcherTest::SetUp();
7501
Chris Yea209fde2020-07-22 13:54:51 -07007502 std::shared_ptr<FakeApplicationHandle> application =
7503 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007504 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
7505 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07007506 mWindow1->setFrame(Rect(0, 0, 100, 100));
7507
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007508 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
7509 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07007510 mWindow2->setFrame(Rect(100, 100, 200, 200));
7511
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007512 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007513 }
7514
7515protected:
7516 sp<FakeWindowHandle> mWindow1;
7517 sp<FakeWindowHandle> mWindow2;
7518
7519 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05007520 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07007521 vec2 vals = windowInfo->transform.transform(point.x, point.y);
7522 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07007523 }
7524
7525 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
7526 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007527 const std::string name = window->getName();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007528 const MotionEvent& motionEvent =
7529 window->consumeMotionEvent(WithMotionAction(expectedAction));
chaviwaf87b3e2019-10-01 16:59:28 -07007530
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007531 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07007532
7533 for (size_t i = 0; i < points.size(); i++) {
7534 float expectedX = points[i].x;
7535 float expectedY = points[i].y;
7536
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007537 EXPECT_EQ(expectedX, motionEvent.getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007538 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007539 << ", got " << motionEvent.getX(i);
7540 EXPECT_EQ(expectedY, motionEvent.getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007541 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007542 << ", got " << motionEvent.getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07007543 }
7544 }
chaviw9eaa22c2020-07-01 16:21:27 -07007545
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007546 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07007547 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007548 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
7549 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07007550
7551 // Always consume from window1 since it's the window that has the InputReceiver
7552 consumeMotionEvent(mWindow1, action, expectedPoints);
7553 }
chaviwaf87b3e2019-10-01 16:59:28 -07007554};
7555
7556TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
7557 // Touch Window 1
7558 PointF touchedPoint = {10, 10};
7559 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007560 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007561
7562 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007563 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007564
7565 // Touch Window 2
7566 touchedPoint = {150, 150};
7567 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007568 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007569}
7570
chaviw9eaa22c2020-07-01 16:21:27 -07007571TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
7572 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07007573 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007574 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007575
7576 // Touch Window 1
7577 PointF touchedPoint = {10, 10};
7578 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007579 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007580 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007581 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007582
7583 // Touch Window 2
7584 touchedPoint = {150, 150};
7585 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007586 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
7587 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007588
chaviw9eaa22c2020-07-01 16:21:27 -07007589 // Update the transform so rotation is set
7590 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007591 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007592 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
7593 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007594}
7595
chaviw9eaa22c2020-07-01 16:21:27 -07007596TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007597 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007598 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007599
7600 // Touch Window 1
7601 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7602 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007603 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007604
7605 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007606 touchedPoints.push_back(PointF{150, 150});
7607 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007608 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007609
chaviw9eaa22c2020-07-01 16:21:27 -07007610 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007611 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007612 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007613
chaviw9eaa22c2020-07-01 16:21:27 -07007614 // Update the transform so rotation is set for Window 2
7615 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007616 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007617 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007618 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007619}
7620
chaviw9eaa22c2020-07-01 16:21:27 -07007621TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007622 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007623 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007624
7625 // Touch Window 1
7626 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7627 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007628 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007629
7630 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007631 touchedPoints.push_back(PointF{150, 150});
7632 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007633
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007634 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007635
7636 // Move both windows
7637 touchedPoints = {{20, 20}, {175, 175}};
7638 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7639 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7640
chaviw9eaa22c2020-07-01 16:21:27 -07007641 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007642
chaviw9eaa22c2020-07-01 16:21:27 -07007643 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007644 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007645 expectedPoints.pop_back();
7646
7647 // Touch Window 2
7648 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007649 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007650 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007651 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007652
7653 // Move both windows
7654 touchedPoints = {{20, 20}, {175, 175}};
7655 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7656 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7657
7658 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007659}
7660
7661TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
7662 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007663 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007664
7665 // Touch Window 1
7666 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7667 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007668 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007669
7670 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007671 touchedPoints.push_back(PointF{150, 150});
7672 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007673
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007674 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007675
7676 // Move both windows
7677 touchedPoints = {{20, 20}, {175, 175}};
7678 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7679 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7680
chaviw9eaa22c2020-07-01 16:21:27 -07007681 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007682}
7683
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007684/**
7685 * When one of the windows is slippery, the touch should not slip into the other window with the
7686 * same input channel.
7687 */
7688TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
7689 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007690 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007691
7692 // Touch down in window 1
7693 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7694 ADISPLAY_ID_DEFAULT, {{50, 50}}));
7695 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
7696
7697 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
7698 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
7699 // getting generated.
7700 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7701 ADISPLAY_ID_DEFAULT, {{150, 150}}));
7702
7703 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
7704}
7705
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007706/**
7707 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
7708 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
7709 * that the pointer is hovering over may have a different transform.
7710 */
7711TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007712 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007713
7714 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007715 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
7716 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7717 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007718 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7719 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007720 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007721 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7722 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
7723 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007724 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
7725 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7726 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
7727}
7728
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007729class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
7730 virtual void SetUp() override {
7731 InputDispatcherTest::SetUp();
7732
Chris Yea209fde2020-07-22 13:54:51 -07007733 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007734 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007735 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
7736 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007737 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007738 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07007739 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007740
7741 // Set focused application.
7742 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7743
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007744 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007745 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007746 mWindow->consumeFocusEvent(true);
7747 }
7748
7749 virtual void TearDown() override {
7750 InputDispatcherTest::TearDown();
7751 mWindow.clear();
7752 }
7753
7754protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007755 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07007756 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007757 sp<FakeWindowHandle> mWindow;
7758 static constexpr PointF WINDOW_LOCATION = {20, 20};
7759
7760 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08007761 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
7762 .x(WINDOW_LOCATION.x)
7763 .y(WINDOW_LOCATION.y);
7764 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7765 .pointer(touchingPointer)
7766 .build());
7767 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7768 .pointer(touchingPointer)
7769 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007770 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007771
7772 sp<FakeWindowHandle> addSpyWindow() {
7773 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007774 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007775 spy->setTrustedOverlay(true);
7776 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007777 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007778 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007779 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007780 return spy;
7781 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007782};
7783
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007784// Send a tap and respond, which should not cause an ANR.
7785TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
7786 tapOnWindow();
7787 mWindow->consumeMotionDown();
7788 mWindow->consumeMotionUp();
7789 ASSERT_TRUE(mDispatcher->waitForIdle());
7790 mFakePolicy->assertNotifyAnrWasNotCalled();
7791}
7792
7793// Send a regular key and respond, which should not cause an ANR.
7794TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007795 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007796 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7797 ASSERT_TRUE(mDispatcher->waitForIdle());
7798 mFakePolicy->assertNotifyAnrWasNotCalled();
7799}
7800
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007801TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
7802 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007803 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007804 mWindow->consumeFocusEvent(false);
7805
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007806 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007807 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7808 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00007809 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007810 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007811 // Key will not go to window because we have no focused window.
7812 // The 'no focused window' ANR timer should start instead.
7813
7814 // Now, the focused application goes away.
7815 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
7816 // The key should get dropped and there should be no ANR.
7817
7818 ASSERT_TRUE(mDispatcher->waitForIdle());
7819 mFakePolicy->assertNotifyAnrWasNotCalled();
7820}
7821
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007822// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007823// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7824// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007825TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007826 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007827 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007828 WINDOW_LOCATION));
7829
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007830 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7831 ASSERT_TRUE(sequenceNum);
7832 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007833 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007834
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007835 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007836 mWindow->consumeMotionEvent(
7837 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007838 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007839 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007840}
7841
7842// Send a key to the app and have the app not respond right away.
7843TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
7844 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007845 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007846 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
7847 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007848 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007849 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007850 ASSERT_TRUE(mDispatcher->waitForIdle());
7851}
7852
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007853// We have a focused application, but no focused window
7854TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007855 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007856 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007857 mWindow->consumeFocusEvent(false);
7858
7859 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007860 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007861 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007862 WINDOW_LOCATION));
7863 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
7864 mDispatcher->waitForIdle();
7865 mFakePolicy->assertNotifyAnrWasNotCalled();
7866
7867 // Once a focused event arrives, we get an ANR for this application
7868 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7869 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007870 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007871 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007872 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007873 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007874 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07007875 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007876 ASSERT_TRUE(mDispatcher->waitForIdle());
7877}
7878
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007879/**
7880 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
7881 * there will not be an ANR.
7882 */
7883TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
7884 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007885 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007886 mWindow->consumeFocusEvent(false);
7887
7888 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07007889 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
7890 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007891 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
7892 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
7893
7894 // Define a valid key down event that is stale (too old).
7895 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007896 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00007897 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007898
7899 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
7900
7901 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007902 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007903 InputEventInjectionSync::WAIT_FOR_RESULT,
7904 INJECT_EVENT_TIMEOUT, policyFlags);
7905 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
7906 << "Injection should fail because the event is stale";
7907
7908 ASSERT_TRUE(mDispatcher->waitForIdle());
7909 mFakePolicy->assertNotifyAnrWasNotCalled();
7910 mWindow->assertNoEvents();
7911}
7912
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007913// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007914// Make sure that we don't notify policy twice about the same ANR.
7915TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007916 const std::chrono::duration appTimeout = 400ms;
7917 mApplication->setDispatchingTimeout(appTimeout);
7918 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7919
Vishnu Nair47074b82020-08-14 11:54:47 -07007920 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007921 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007922 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007923
7924 // Once a focused event arrives, we get an ANR for this application
7925 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7926 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007927 const std::chrono::duration eventInjectionTimeout = 100ms;
7928 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007929 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007930 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007931 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
7932 /*allowKeyRepeat=*/false);
7933 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
7934 << "result=" << ftl::enum_string(result);
7935 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
7936 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
7937 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
7938 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007939
Vishnu Naire4df8752022-09-08 09:17:55 -07007940 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007941 // ANR should not be raised again. It is up to policy to do that if it desires.
7942 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007943
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007944 // If we now get a focused window, the ANR should stop, but the policy handles that via
7945 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007946 ASSERT_TRUE(mDispatcher->waitForIdle());
7947}
7948
7949// We have a focused application, but no focused window
7950TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007951 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007952 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007953 mWindow->consumeFocusEvent(false);
7954
7955 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007956 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007957
Vishnu Naire4df8752022-09-08 09:17:55 -07007958 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7959 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007960
7961 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007962 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007963 ASSERT_TRUE(mDispatcher->waitForIdle());
7964 mWindow->assertNoEvents();
7965}
7966
7967/**
7968 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
7969 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
7970 * If we process 1 of the events, but ANR on the second event with the same timestamp,
7971 * the ANR mechanism should still work.
7972 *
7973 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
7974 * DOWN event, while not responding on the second one.
7975 */
7976TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
7977 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007978 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007979 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7980 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7981 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007982 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007983
7984 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007985 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007986 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7987 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7988 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007989 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007990
7991 // We have now sent down and up. Let's consume first event and then ANR on the second.
7992 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7993 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007994 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007995}
7996
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007997// A spy window can receive an ANR
7998TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
7999 sp<FakeWindowHandle> spy = addSpyWindow();
8000
8001 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008002 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008003 WINDOW_LOCATION));
8004 mWindow->consumeMotionDown();
8005
8006 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
8007 ASSERT_TRUE(sequenceNum);
8008 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008009 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008010
8011 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008012 spy->consumeMotionEvent(
8013 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008014 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008015 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008016}
8017
8018// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008019// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008020TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
8021 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008022
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008023 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008024 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008025 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008026 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008027
8028 // Stuck on the ACTION_UP
8029 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008030 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008031
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008032 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008033 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008034 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8035 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008036
8037 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8038 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008039 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008040 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008041 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008042}
8043
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008044// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008045// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008046TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
8047 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008048
8049 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008050 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8051 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008052
8053 mWindow->consumeMotionDown();
8054 // Stuck on the ACTION_UP
8055 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008056 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008057
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008058 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008059 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008060 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8061 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008062
8063 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8064 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008065 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008066 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008067 spy->assertNoEvents();
8068}
8069
8070TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008071 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008072
Prabir Pradhanfb549072023-10-05 19:17:36 +00008073 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008074
8075 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008076 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008077 WINDOW_LOCATION));
8078
8079 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8080 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
8081 ASSERT_TRUE(consumeSeq);
8082
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008083 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
8084 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008085
8086 monitor.finishEvent(*consumeSeq);
8087 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
8088
8089 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008090 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008091}
8092
8093// If a window is unresponsive, then you get anr. if the window later catches up and starts to
8094// process events, you don't get an anr. When the window later becomes unresponsive again, you
8095// get an ANR again.
8096// 1. tap -> block on ACTION_UP -> receive ANR
8097// 2. consume all pending events (= queue becomes healthy again)
8098// 3. tap again -> block on ACTION_UP again -> receive ANR second time
8099TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
8100 tapOnWindow();
8101
8102 mWindow->consumeMotionDown();
8103 // Block on ACTION_UP
8104 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008105 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008106 mWindow->consumeMotionUp(); // Now the connection should be healthy again
8107 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008108 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008109 mWindow->assertNoEvents();
8110
8111 tapOnWindow();
8112 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008113 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008114 mWindow->consumeMotionUp();
8115
8116 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008117 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008118 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008119 mWindow->assertNoEvents();
8120}
8121
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008122// If a connection remains unresponsive for a while, make sure policy is only notified once about
8123// it.
8124TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008125 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008126 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008127 WINDOW_LOCATION));
8128
8129 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008130 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008131 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008132 // 'notifyConnectionUnresponsive' should only be called once per connection
8133 mFakePolicy->assertNotifyAnrWasNotCalled();
8134 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008135 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008136 mWindow->consumeMotionEvent(
8137 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008138 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008139 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008140 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008141 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008142}
8143
8144/**
8145 * 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 -07008146 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008147 *
8148 * Warning!!!
8149 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8150 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008151 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008152 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8153 *
8154 * If that value changes, this test should also change.
8155 */
8156TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
8157 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008158 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008159
8160 tapOnWindow();
8161 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
8162 ASSERT_TRUE(downSequenceNum);
8163 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
8164 ASSERT_TRUE(upSequenceNum);
8165 // Don't finish the events yet, and send a key
8166 // Injection will "succeed" because we will eventually give up and send the key to the focused
8167 // window even if motions are still being processed. But because the injection timeout is short,
8168 // we will receive INJECTION_TIMED_OUT as the result.
8169
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008170 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008171 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8172 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008173 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008174 // Key will not be sent to the window, yet, because the window is still processing events
8175 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008176 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
8177 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8178 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8179 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008180
8181 std::this_thread::sleep_for(500ms);
8182 // if we wait long enough though, dispatcher will give up, and still send the key
8183 // to the focused window, even though we have not yet finished the motion event
8184 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8185 mWindow->finishEvent(*downSequenceNum);
8186 mWindow->finishEvent(*upSequenceNum);
8187}
8188
8189/**
8190 * If a window is processing a motion event, and then a key event comes in, the key event should
8191 * not go to the focused window until the motion is processed.
8192 * If then a new motion comes in, then the pending key event should be going to the currently
8193 * focused window right away.
8194 */
8195TEST_F(InputDispatcherSingleWindowAnr,
8196 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
8197 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008198 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008199
8200 tapOnWindow();
8201 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
8202 ASSERT_TRUE(downSequenceNum);
8203 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
8204 ASSERT_TRUE(upSequenceNum);
8205 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008206 mDispatcher->notifyKey(
8207 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
8208 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8209 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008210 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008211 // Make sure the `assertNoEvents` check doesn't take too long. It uses
8212 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8213 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8214 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008215
8216 // Now tap down again. It should cause the pending key to go to the focused window right away.
8217 tapOnWindow();
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008218 mWindow->consumeKeyEvent(WithKeyAction(AKEY_EVENT_ACTION_DOWN)); // it doesn't matter that we
8219 // haven't ack'd the other events yet. We can finish events in any order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008220 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
8221 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008222 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8223 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008224 mWindow->assertNoEvents();
8225}
8226
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07008227/**
8228 * Send an event to the app and have the app not respond right away.
8229 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8230 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
8231 * At some point, the window becomes responsive again.
8232 * Ensure that subsequent events get dropped, and the next gesture is delivered.
8233 */
8234TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
8235 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8236 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
8237 .build());
8238
8239 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
8240 ASSERT_TRUE(sequenceNum);
8241 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8242 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
8243
8244 mWindow->finishEvent(*sequenceNum);
8245 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
8246 ASSERT_TRUE(mDispatcher->waitForIdle());
8247 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
8248
8249 // Now that the window is responsive, let's continue the gesture.
8250 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8251 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8252 .build());
8253
8254 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8255 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8256 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8257 .build());
8258
8259 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8260 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8261 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8262 .build());
8263 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8264 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8265 .build());
8266 // We already canceled this pointer, so the window shouldn't get any new events.
8267 mWindow->assertNoEvents();
8268
8269 // Start another one.
8270 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8271 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
8272 .build());
8273 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8274}
8275
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008276class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
8277 virtual void SetUp() override {
8278 InputDispatcherTest::SetUp();
8279
Chris Yea209fde2020-07-22 13:54:51 -07008280 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008281 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008282 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
8283 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008284 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008285 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008286 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008287
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008288 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
8289 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008290 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008291 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008292
8293 // Set focused application.
8294 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07008295 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008296
8297 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008298 mDispatcher->onWindowInfosChanged(
8299 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008300 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008301 mFocusedWindow->consumeFocusEvent(true);
8302 }
8303
8304 virtual void TearDown() override {
8305 InputDispatcherTest::TearDown();
8306
8307 mUnfocusedWindow.clear();
8308 mFocusedWindow.clear();
8309 }
8310
8311protected:
Chris Yea209fde2020-07-22 13:54:51 -07008312 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008313 sp<FakeWindowHandle> mUnfocusedWindow;
8314 sp<FakeWindowHandle> mFocusedWindow;
8315 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
8316 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
8317 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
8318
8319 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
8320
8321 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
8322
8323private:
8324 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008325 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008326 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008327 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008328 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008329 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008330 location));
8331 }
8332};
8333
8334// If we have 2 windows that are both unresponsive, the one with the shortest timeout
8335// should be ANR'd first.
8336TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008337 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008338 injectMotionEvent(*mDispatcher,
8339 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8340 AINPUT_SOURCE_TOUCHSCREEN)
8341 .pointer(PointerBuilder(0, ToolType::FINGER)
8342 .x(FOCUSED_WINDOW_LOCATION.x)
8343 .y(FOCUSED_WINDOW_LOCATION.y))
8344 .build()));
8345 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8346 injectMotionEvent(*mDispatcher,
8347 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
8348 AINPUT_SOURCE_TOUCHSCREEN)
8349 .pointer(PointerBuilder(0, ToolType::FINGER)
8350 .x(FOCUSED_WINDOW_LOCATION.x)
8351 .y(FOCUSED_WINDOW_LOCATION.y))
8352 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008353 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008354 mFocusedWindow->consumeMotionUp();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008355 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008356 // We consumed all events, so no ANR
8357 ASSERT_TRUE(mDispatcher->waitForIdle());
8358 mFakePolicy->assertNotifyAnrWasNotCalled();
8359
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008360 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008361 injectMotionEvent(*mDispatcher,
8362 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8363 AINPUT_SOURCE_TOUCHSCREEN)
8364 .pointer(PointerBuilder(0, ToolType::FINGER)
8365 .x(FOCUSED_WINDOW_LOCATION.x)
8366 .y(FOCUSED_WINDOW_LOCATION.y))
8367 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008368 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
8369 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008370
8371 const std::chrono::duration timeout =
8372 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008373 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008374
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008375 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008376 mFocusedWindow->consumeMotionDown();
8377 // This cancel is generated because the connection was unresponsive
8378 mFocusedWindow->consumeMotionCancel();
8379 mFocusedWindow->assertNoEvents();
8380 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008381 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008382 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8383 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008384 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008385}
8386
8387// If we have 2 windows with identical timeouts that are both unresponsive,
8388// it doesn't matter which order they should have ANR.
8389// But we should receive ANR for both.
8390TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
8391 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008392 mUnfocusedWindow->setDispatchingTimeout(
8393 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008394 mDispatcher->onWindowInfosChanged(
8395 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008396
8397 tapOnFocusedWindow();
8398 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008399 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008400 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
8401 mFocusedWindow->getDispatchingTimeout(
8402 DISPATCHING_TIMEOUT)),
8403 mFakePolicy->getUnresponsiveWindowToken(0ms)};
8404
8405 ASSERT_THAT(anrConnectionTokens,
8406 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8407 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008408
8409 ASSERT_TRUE(mDispatcher->waitForIdle());
8410 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008411
8412 mFocusedWindow->consumeMotionDown();
8413 mFocusedWindow->consumeMotionUp();
8414 mUnfocusedWindow->consumeMotionOutside();
8415
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008416 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
8417 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008418
8419 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008420 ASSERT_THAT(responsiveTokens,
8421 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8422 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008423 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008424}
8425
8426// If a window is already not responding, the second tap on the same window should be ignored.
8427// We should also log an error to account for the dropped event (not tested here).
8428// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
8429TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
8430 tapOnFocusedWindow();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008431 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008432 // Receive the events, but don't respond
8433 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
8434 ASSERT_TRUE(downEventSequenceNum);
8435 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
8436 ASSERT_TRUE(upEventSequenceNum);
8437 const std::chrono::duration timeout =
8438 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008439 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008440
8441 // Tap once again
8442 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008443 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008444 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008445 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008446 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008447 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008448 FOCUSED_WINDOW_LOCATION));
8449 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
8450 // valid touch target
8451 mUnfocusedWindow->assertNoEvents();
8452
8453 // Consume the first tap
8454 mFocusedWindow->finishEvent(*downEventSequenceNum);
8455 mFocusedWindow->finishEvent(*upEventSequenceNum);
8456 ASSERT_TRUE(mDispatcher->waitForIdle());
8457 // The second tap did not go to the focused window
8458 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008459 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08008460 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8461 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008462 mFakePolicy->assertNotifyAnrWasNotCalled();
8463}
8464
8465// If you tap outside of all windows, there will not be ANR
8466TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008467 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008468 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008469 LOCATION_OUTSIDE_ALL_WINDOWS));
8470 ASSERT_TRUE(mDispatcher->waitForIdle());
8471 mFakePolicy->assertNotifyAnrWasNotCalled();
8472}
8473
8474// Since the focused window is paused, tapping on it should not produce any events
8475TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
8476 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008477 mDispatcher->onWindowInfosChanged(
8478 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008479
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008480 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008481 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008482 FOCUSED_WINDOW_LOCATION));
8483
8484 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
8485 ASSERT_TRUE(mDispatcher->waitForIdle());
8486 // Should not ANR because the window is paused, and touches shouldn't go to it
8487 mFakePolicy->assertNotifyAnrWasNotCalled();
8488
8489 mFocusedWindow->assertNoEvents();
8490 mUnfocusedWindow->assertNoEvents();
8491}
8492
8493/**
8494 * 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 -07008495 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008496 * If a different window becomes focused at this time, the key should go to that window instead.
8497 *
8498 * Warning!!!
8499 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8500 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008501 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008502 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8503 *
8504 * If that value changes, this test should also change.
8505 */
8506TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
8507 // Set a long ANR timeout to prevent it from triggering
8508 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008509 mDispatcher->onWindowInfosChanged(
8510 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008511
8512 tapOnUnfocusedWindow();
8513 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
8514 ASSERT_TRUE(downSequenceNum);
8515 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
8516 ASSERT_TRUE(upSequenceNum);
8517 // Don't finish the events yet, and send a key
8518 // Injection will succeed because we will eventually give up and send the key to the focused
8519 // window even if motions are still being processed.
8520
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008521 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008522 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8523 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008524 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008525 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008526 // and the key remains pending, waiting for the touch events to be processed.
8527 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
8528 // under the hood.
8529 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8530 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008531
8532 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07008533 mFocusedWindow->setFocusable(false);
8534 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008535 mDispatcher->onWindowInfosChanged(
8536 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008537 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008538
8539 // Focus events should precede the key events
8540 mUnfocusedWindow->consumeFocusEvent(true);
8541 mFocusedWindow->consumeFocusEvent(false);
8542
8543 // Finish the tap events, which should unblock dispatcher
8544 mUnfocusedWindow->finishEvent(*downSequenceNum);
8545 mUnfocusedWindow->finishEvent(*upSequenceNum);
8546
8547 // Now that all queues are cleared and no backlog in the connections, the key event
8548 // can finally go to the newly focused "mUnfocusedWindow".
8549 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8550 mFocusedWindow->assertNoEvents();
8551 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008552 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008553}
8554
8555// When the touch stream is split across 2 windows, and one of them does not respond,
8556// then ANR should be raised and the touch should be canceled for the unresponsive window.
8557// The other window should not be affected by that.
8558TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
8559 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00008560 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8561 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8562 {FOCUSED_WINDOW_LOCATION}));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008563 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008564
8565 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00008566 mDispatcher->notifyMotion(
8567 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8568 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008569
8570 const std::chrono::duration timeout =
8571 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008572 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008573
8574 mUnfocusedWindow->consumeMotionDown();
8575 mFocusedWindow->consumeMotionDown();
8576 // Focused window may or may not receive ACTION_MOVE
8577 // But it should definitely receive ACTION_CANCEL due to the ANR
8578 InputEvent* event;
8579 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
8580 ASSERT_TRUE(moveOrCancelSequenceNum);
8581 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
8582 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008583 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008584 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
8585 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
8586 mFocusedWindow->consumeMotionCancel();
8587 } else {
8588 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
8589 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008590 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008591 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8592 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008593
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008594 mUnfocusedWindow->assertNoEvents();
8595 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008596 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008597}
8598
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008599/**
8600 * If we have no focused window, and a key comes in, we start the ANR timer.
8601 * The focused application should add a focused window before the timer runs out to prevent ANR.
8602 *
8603 * If the user touches another application during this time, the key should be dropped.
8604 * Next, if a new focused window comes in, without toggling the focused application,
8605 * then no ANR should occur.
8606 *
8607 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
8608 * but in some cases the policy may not update the focused application.
8609 */
8610TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
8611 std::shared_ptr<FakeApplicationHandle> focusedApplication =
8612 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07008613 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008614 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
8615 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
8616 mFocusedWindow->setFocusable(false);
8617
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008618 mDispatcher->onWindowInfosChanged(
8619 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008620 mFocusedWindow->consumeFocusEvent(false);
8621
8622 // Send a key. The ANR timer should start because there is no focused window.
8623 // 'focusedApplication' will get blamed if this timer completes.
8624 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008625 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008626 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8627 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00008628 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008629 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008630
8631 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
8632 // then the injected touches won't cause the focused event to get dropped.
8633 // The dispatcher only checks for whether the queue should be pruned upon queueing.
8634 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
8635 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
8636 // For this test, it means that the key would get delivered to the window once it becomes
8637 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008638 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008639
8640 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00008641 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8642 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8643 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008644
8645 // We do not consume the motion right away, because that would require dispatcher to first
8646 // process (== drop) the key event, and by that time, ANR will be raised.
8647 // Set the focused window first.
8648 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008649 mDispatcher->onWindowInfosChanged(
8650 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008651 setFocusedWindow(mFocusedWindow);
8652 mFocusedWindow->consumeFocusEvent(true);
8653 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
8654 // to another application. This could be a bug / behaviour in the policy.
8655
8656 mUnfocusedWindow->consumeMotionDown();
8657
8658 ASSERT_TRUE(mDispatcher->waitForIdle());
8659 // Should not ANR because we actually have a focused window. It was just added too slowly.
8660 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
8661}
8662
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008663// These tests ensure we cannot send touch events to a window that's positioned behind a window
8664// that has feature NO_INPUT_CHANNEL.
8665// Layout:
8666// Top (closest to user)
8667// mNoInputWindow (above all windows)
8668// mBottomWindow
8669// Bottom (furthest from user)
8670class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
8671 virtual void SetUp() override {
8672 InputDispatcherTest::SetUp();
8673
8674 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008675 mNoInputWindow =
8676 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8677 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008678 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008679 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008680 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
8681 // It's perfectly valid for this window to not have an associated input channel
8682
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008683 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
8684 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008685 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
8686
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008687 mDispatcher->onWindowInfosChanged(
8688 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008689 }
8690
8691protected:
8692 std::shared_ptr<FakeApplicationHandle> mApplication;
8693 sp<FakeWindowHandle> mNoInputWindow;
8694 sp<FakeWindowHandle> mBottomWindow;
8695};
8696
8697TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
8698 PointF touchedPoint = {10, 10};
8699
Prabir Pradhan678438e2023-04-13 19:32:51 +00008700 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8701 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8702 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008703
8704 mNoInputWindow->assertNoEvents();
8705 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
8706 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
8707 // and therefore should prevent mBottomWindow from receiving touches
8708 mBottomWindow->assertNoEvents();
8709}
8710
8711/**
8712 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
8713 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
8714 */
8715TEST_F(InputDispatcherMultiWindowOcclusionTests,
8716 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008717 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8718 "Window with input channel and NO_INPUT_CHANNEL",
8719 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008720
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008721 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008722 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008723 mDispatcher->onWindowInfosChanged(
8724 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008725
8726 PointF touchedPoint = {10, 10};
8727
Prabir Pradhan678438e2023-04-13 19:32:51 +00008728 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8729 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8730 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008731
8732 mNoInputWindow->assertNoEvents();
8733 mBottomWindow->assertNoEvents();
8734}
8735
Vishnu Nair958da932020-08-21 17:12:37 -07008736class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
8737protected:
8738 std::shared_ptr<FakeApplicationHandle> mApp;
8739 sp<FakeWindowHandle> mWindow;
8740 sp<FakeWindowHandle> mMirror;
8741
8742 virtual void SetUp() override {
8743 InputDispatcherTest::SetUp();
8744 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008745 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
8746 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
8747 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07008748 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
8749 mWindow->setFocusable(true);
8750 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008751 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008752 }
8753};
8754
8755TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
8756 // Request focus on a mirrored window
8757 setFocusedWindow(mMirror);
8758
8759 // window gets focused
8760 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008761 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008762 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008763 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8764}
8765
8766// A focused & mirrored window remains focused only if the window and its mirror are both
8767// focusable.
8768TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
8769 setFocusedWindow(mMirror);
8770
8771 // window gets focused
8772 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008773 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008774 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008775 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008776 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008777 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008778 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8779
8780 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008781 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008782
8783 // window loses focus since one of the windows associated with the token in not focusable
8784 mWindow->consumeFocusEvent(false);
8785
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008786 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008787 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008788 mWindow->assertNoEvents();
8789}
8790
8791// A focused & mirrored window remains focused until the window and its mirror both become
8792// invisible.
8793TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
8794 setFocusedWindow(mMirror);
8795
8796 // window gets focused
8797 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008798 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008799 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008800 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008801 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008802 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008803 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8804
8805 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008806 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008807
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008808 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008809 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008810 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008811 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008812 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008813 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8814
8815 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008816 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008817
8818 // window loses focus only after all windows associated with the token become invisible.
8819 mWindow->consumeFocusEvent(false);
8820
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008821 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008822 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008823 mWindow->assertNoEvents();
8824}
8825
8826// A focused & mirrored window remains focused until both windows are removed.
8827TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
8828 setFocusedWindow(mMirror);
8829
8830 // window gets focused
8831 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008832 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008833 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008834 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008835 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008836 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008837 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8838
8839 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008840 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008841
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008842 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008843 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008844 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008845 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008846 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008847 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8848
8849 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008850 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008851 mWindow->consumeFocusEvent(false);
8852
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008853 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008854 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008855 mWindow->assertNoEvents();
8856}
8857
8858// Focus request can be pending until one window becomes visible.
8859TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
8860 // Request focus on an invisible mirror.
8861 mWindow->setVisible(false);
8862 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008863 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008864 setFocusedWindow(mMirror);
8865
8866 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008867 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008868 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
8869 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07008870
8871 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008872 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008873
8874 // window gets focused
8875 mWindow->consumeFocusEvent(true);
8876 // window gets the pending key event
8877 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8878}
Prabir Pradhan99987712020-11-10 18:43:05 -08008879
8880class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
8881protected:
8882 std::shared_ptr<FakeApplicationHandle> mApp;
8883 sp<FakeWindowHandle> mWindow;
8884 sp<FakeWindowHandle> mSecondWindow;
8885
8886 void SetUp() override {
8887 InputDispatcherTest::SetUp();
8888 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008889 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008890 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008891 mSecondWindow =
8892 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008893 mSecondWindow->setFocusable(true);
8894
8895 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008896 mDispatcher->onWindowInfosChanged(
8897 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08008898
8899 setFocusedWindow(mWindow);
8900 mWindow->consumeFocusEvent(true);
8901 }
8902
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008903 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008904 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08008905 }
8906
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008907 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
8908 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08008909 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008910 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
8911 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008912 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008913 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08008914 }
8915};
8916
8917TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
8918 // Ensure that capture cannot be obtained for unfocused windows.
8919 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
8920 mFakePolicy->assertSetPointerCaptureNotCalled();
8921 mSecondWindow->assertNoEvents();
8922
8923 // Ensure that capture can be enabled from the focus window.
8924 requestAndVerifyPointerCapture(mWindow, true);
8925
8926 // Ensure that capture cannot be disabled from a window that does not have capture.
8927 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
8928 mFakePolicy->assertSetPointerCaptureNotCalled();
8929
8930 // Ensure that capture can be disabled from the window with capture.
8931 requestAndVerifyPointerCapture(mWindow, false);
8932}
8933
8934TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008935 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008936
8937 setFocusedWindow(mSecondWindow);
8938
8939 // Ensure that the capture disabled event was sent first.
8940 mWindow->consumeCaptureEvent(false);
8941 mWindow->consumeFocusEvent(false);
8942 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008943 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008944
8945 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008946 notifyPointerCaptureChanged({});
8947 notifyPointerCaptureChanged(request);
8948 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08008949 mWindow->assertNoEvents();
8950 mSecondWindow->assertNoEvents();
8951 mFakePolicy->assertSetPointerCaptureNotCalled();
8952}
8953
8954TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008955 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008956
8957 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008958 notifyPointerCaptureChanged({});
8959 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008960
8961 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008962 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008963 mWindow->consumeCaptureEvent(false);
8964 mWindow->assertNoEvents();
8965}
8966
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008967TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
8968 requestAndVerifyPointerCapture(mWindow, true);
8969
8970 // The first window loses focus.
8971 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008972 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008973 mWindow->consumeCaptureEvent(false);
8974
8975 // Request Pointer Capture from the second window before the notification from InputReader
8976 // arrives.
8977 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008978 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008979
8980 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008981 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008982
8983 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008984 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008985
8986 mSecondWindow->consumeFocusEvent(true);
8987 mSecondWindow->consumeCaptureEvent(true);
8988}
8989
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008990TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
8991 // App repeatedly enables and disables capture.
8992 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8993 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8994 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8995 mFakePolicy->assertSetPointerCaptureCalled(false);
8996 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8997 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8998
8999 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
9000 // first request is now stale, this should do nothing.
9001 notifyPointerCaptureChanged(firstRequest);
9002 mWindow->assertNoEvents();
9003
9004 // InputReader notifies that the second request was enabled.
9005 notifyPointerCaptureChanged(secondRequest);
9006 mWindow->consumeCaptureEvent(true);
9007}
9008
Prabir Pradhan7092e262022-05-03 16:51:09 +00009009TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
9010 requestAndVerifyPointerCapture(mWindow, true);
9011
9012 // App toggles pointer capture off and on.
9013 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9014 mFakePolicy->assertSetPointerCaptureCalled(false);
9015
9016 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9017 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9018
9019 // InputReader notifies that the latest "enable" request was processed, while skipping over the
9020 // preceding "disable" request.
9021 notifyPointerCaptureChanged(enableRequest);
9022
9023 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
9024 // any notifications.
9025 mWindow->assertNoEvents();
9026}
9027
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009028/**
9029 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
9030 * mouse movements don't affect the previous mouse hovering state.
9031 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
9032 * HOVER_MOVE events).
9033 */
9034TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
9035 // Mouse hover on the window
9036 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
9037 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9038 .build());
9039 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9040 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9041 .build());
9042
9043 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
9044 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
9045
9046 // Start pointer capture
9047 requestAndVerifyPointerCapture(mWindow, true);
9048
9049 // Send some relative mouse movements and receive them in the window.
9050 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
9051 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
9052 .build());
9053 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
9054 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
9055
9056 // Stop pointer capture
9057 requestAndVerifyPointerCapture(mWindow, false);
9058
9059 // Continue hovering on the window
9060 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9061 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
9062 .build());
9063 mWindow->consumeMotionEvent(
9064 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
9065
9066 mWindow->assertNoEvents();
9067}
9068
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009069class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
9070protected:
9071 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00009072
9073 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
9074 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
9075
9076 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
9077 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9078
9079 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
9080 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
9081 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9082 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
9083 MAXIMUM_OBSCURING_OPACITY);
9084
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009085 static constexpr gui::Uid TOUCHED_APP_UID{10001};
9086 static constexpr gui::Uid APP_B_UID{10002};
9087 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009088
9089 sp<FakeWindowHandle> mTouchWindow;
9090
9091 virtual void SetUp() override {
9092 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009093 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009094 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
9095 }
9096
9097 virtual void TearDown() override {
9098 InputDispatcherTest::TearDown();
9099 mTouchWindow.clear();
9100 }
9101
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009102 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05009103 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009104 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009105 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009106 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009107 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009108 return window;
9109 }
9110
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009111 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009112 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
9113 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009114 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009115 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009116 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009117 return window;
9118 }
9119
9120 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009121 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9122 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9123 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009124 }
9125};
9126
9127TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009128 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009129 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009130 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009131
9132 touch();
9133
9134 mTouchWindow->assertNoEvents();
9135}
9136
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009137TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00009138 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
9139 const sp<FakeWindowHandle>& w =
9140 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009141 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009142
9143 touch();
9144
9145 mTouchWindow->assertNoEvents();
9146}
9147
9148TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009149 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
9150 const sp<FakeWindowHandle>& w =
9151 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009152 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009153
9154 touch();
9155
9156 w->assertNoEvents();
9157}
9158
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009159TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009160 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009161 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009162
9163 touch();
9164
9165 mTouchWindow->consumeAnyMotionDown();
9166}
9167
9168TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009169 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009170 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009171 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009172 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009173
9174 touch({PointF{100, 100}});
9175
9176 mTouchWindow->consumeAnyMotionDown();
9177}
9178
9179TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009180 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009181 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009182 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009183
9184 touch();
9185
9186 mTouchWindow->consumeAnyMotionDown();
9187}
9188
9189TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
9190 const sp<FakeWindowHandle>& w =
9191 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009192 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009193
9194 touch();
9195
9196 mTouchWindow->consumeAnyMotionDown();
9197}
9198
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009199TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
9200 const sp<FakeWindowHandle>& w =
9201 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009202 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009203
9204 touch();
9205
9206 w->assertNoEvents();
9207}
9208
9209/**
9210 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
9211 * inside) while letting them pass-through. Note that even though touch passes through the occluding
9212 * window, the occluding window will still receive ACTION_OUTSIDE event.
9213 */
9214TEST_F(InputDispatcherUntrustedTouchesTest,
9215 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
9216 const sp<FakeWindowHandle>& w =
9217 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009218 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009219 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009220
9221 touch();
9222
9223 w->consumeMotionOutside();
9224}
9225
9226TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
9227 const sp<FakeWindowHandle>& w =
9228 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009229 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009230 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009231
9232 touch();
9233
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009234 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009235}
9236
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009237TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009238 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009239 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9240 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009241 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009242
9243 touch();
9244
9245 mTouchWindow->consumeAnyMotionDown();
9246}
9247
9248TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
9249 const sp<FakeWindowHandle>& w =
9250 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9251 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009252 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009253
9254 touch();
9255
9256 mTouchWindow->consumeAnyMotionDown();
9257}
9258
9259TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009260 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009261 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9262 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009263 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009264
9265 touch();
9266
9267 mTouchWindow->assertNoEvents();
9268}
9269
9270TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
9271 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
9272 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009273 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9274 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009275 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009276 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9277 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009278 mDispatcher->onWindowInfosChanged(
9279 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009280
9281 touch();
9282
9283 mTouchWindow->assertNoEvents();
9284}
9285
9286TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
9287 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
9288 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009289 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9290 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009291 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009292 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9293 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009294 mDispatcher->onWindowInfosChanged(
9295 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009296
9297 touch();
9298
9299 mTouchWindow->consumeAnyMotionDown();
9300}
9301
9302TEST_F(InputDispatcherUntrustedTouchesTest,
9303 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
9304 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009305 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9306 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009307 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009308 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9309 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009310 mDispatcher->onWindowInfosChanged(
9311 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009312
9313 touch();
9314
9315 mTouchWindow->consumeAnyMotionDown();
9316}
9317
9318TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
9319 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009320 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9321 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009322 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009323 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9324 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009325 mDispatcher->onWindowInfosChanged(
9326 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009327
9328 touch();
9329
9330 mTouchWindow->assertNoEvents();
9331}
9332
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009333TEST_F(InputDispatcherUntrustedTouchesTest,
9334 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
9335 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009336 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9337 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009338 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009339 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9340 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009341 mDispatcher->onWindowInfosChanged(
9342 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009343
9344 touch();
9345
9346 mTouchWindow->assertNoEvents();
9347}
9348
9349TEST_F(InputDispatcherUntrustedTouchesTest,
9350 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
9351 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009352 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9353 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009354 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009355 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9356 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009357 mDispatcher->onWindowInfosChanged(
9358 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009359
9360 touch();
9361
9362 mTouchWindow->consumeAnyMotionDown();
9363}
9364
9365TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
9366 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009367 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9368 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009369 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009370
9371 touch();
9372
9373 mTouchWindow->consumeAnyMotionDown();
9374}
9375
9376TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
9377 const sp<FakeWindowHandle>& w =
9378 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009379 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009380
9381 touch();
9382
9383 mTouchWindow->consumeAnyMotionDown();
9384}
9385
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009386TEST_F(InputDispatcherUntrustedTouchesTest,
9387 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
9388 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9389 const sp<FakeWindowHandle>& w =
9390 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009391 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009392
9393 touch();
9394
9395 mTouchWindow->assertNoEvents();
9396}
9397
9398TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
9399 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9400 const sp<FakeWindowHandle>& w =
9401 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009402 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009403
9404 touch();
9405
9406 mTouchWindow->consumeAnyMotionDown();
9407}
9408
9409TEST_F(InputDispatcherUntrustedTouchesTest,
9410 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
9411 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
9412 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009413 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9414 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009415 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009416
9417 touch();
9418
9419 mTouchWindow->consumeAnyMotionDown();
9420}
9421
9422TEST_F(InputDispatcherUntrustedTouchesTest,
9423 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
9424 const sp<FakeWindowHandle>& w1 =
9425 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9426 OPACITY_BELOW_THRESHOLD);
9427 const sp<FakeWindowHandle>& w2 =
9428 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9429 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009430 mDispatcher->onWindowInfosChanged(
9431 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009432
9433 touch();
9434
9435 mTouchWindow->assertNoEvents();
9436}
9437
9438/**
9439 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
9440 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
9441 * (which alone would result in allowing touches) does not affect the blocking behavior.
9442 */
9443TEST_F(InputDispatcherUntrustedTouchesTest,
9444 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
9445 const sp<FakeWindowHandle>& wB =
9446 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9447 OPACITY_BELOW_THRESHOLD);
9448 const sp<FakeWindowHandle>& wC =
9449 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9450 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009451 mDispatcher->onWindowInfosChanged(
9452 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009453
9454 touch();
9455
9456 mTouchWindow->assertNoEvents();
9457}
9458
9459/**
9460 * This test is testing that a window from a different UID but with same application token doesn't
9461 * block the touch. Apps can share the application token for close UI collaboration for example.
9462 */
9463TEST_F(InputDispatcherUntrustedTouchesTest,
9464 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
9465 const sp<FakeWindowHandle>& w =
9466 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
9467 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009468 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009469
9470 touch();
9471
9472 mTouchWindow->consumeAnyMotionDown();
9473}
9474
arthurhungb89ccb02020-12-30 16:19:01 +08009475class InputDispatcherDragTests : public InputDispatcherTest {
9476protected:
9477 std::shared_ptr<FakeApplicationHandle> mApp;
9478 sp<FakeWindowHandle> mWindow;
9479 sp<FakeWindowHandle> mSecondWindow;
9480 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009481 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009482 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
9483 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08009484
9485 void SetUp() override {
9486 InputDispatcherTest::SetUp();
9487 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009488 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009489 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009490
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009491 mSecondWindow =
9492 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009493 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009494
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009495 mSpyWindow =
9496 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009497 mSpyWindow->setSpy(true);
9498 mSpyWindow->setTrustedOverlay(true);
9499 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
9500
arthurhungb89ccb02020-12-30 16:19:01 +08009501 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009502 mDispatcher->onWindowInfosChanged(
9503 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
9504 {},
9505 0,
9506 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009507 }
9508
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009509 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
9510 switch (fromSource) {
9511 case AINPUT_SOURCE_TOUCHSCREEN:
9512 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009513 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009514 ADISPLAY_ID_DEFAULT, {50, 50}))
9515 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9516 break;
9517 case AINPUT_SOURCE_STYLUS:
9518 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009519 injectMotionEvent(*mDispatcher,
9520 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9521 AINPUT_SOURCE_STYLUS)
9522 .buttonState(
9523 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
9524 .pointer(PointerBuilder(0, ToolType::STYLUS)
9525 .x(50)
9526 .y(50))
9527 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009528 break;
9529 case AINPUT_SOURCE_MOUSE:
9530 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009531 injectMotionEvent(*mDispatcher,
9532 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9533 AINPUT_SOURCE_MOUSE)
9534 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
9535 .pointer(PointerBuilder(MOUSE_POINTER_ID,
9536 ToolType::MOUSE)
9537 .x(50)
9538 .y(50))
9539 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009540 break;
9541 default:
9542 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
9543 }
arthurhungb89ccb02020-12-30 16:19:01 +08009544
9545 // Window should receive motion event.
9546 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009547 // Spy window should also receive motion event
9548 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00009549 }
9550
9551 // Start performing drag, we will create a drag window and transfer touch to it.
9552 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
9553 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009554 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00009555 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009556 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00009557 }
arthurhungb89ccb02020-12-30 16:19:01 +08009558
9559 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009560 mDragWindow =
9561 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009562 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009563 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
9564 *mWindow->getInfo(), *mSecondWindow->getInfo()},
9565 {},
9566 0,
9567 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009568
9569 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00009570 bool transferred =
9571 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00009572 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00009573 if (transferred) {
9574 mWindow->consumeMotionCancel();
9575 mDragWindow->consumeMotionDown();
9576 }
9577 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08009578 }
9579};
9580
9581TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009582 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08009583
9584 // Move on window.
9585 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009586 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009587 ADISPLAY_ID_DEFAULT, {50, 50}))
9588 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9589 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9590 mWindow->consumeDragEvent(false, 50, 50);
9591 mSecondWindow->assertNoEvents();
9592
9593 // Move to another window.
9594 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009595 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009596 ADISPLAY_ID_DEFAULT, {150, 50}))
9597 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9598 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9599 mWindow->consumeDragEvent(true, 150, 50);
9600 mSecondWindow->consumeDragEvent(false, 50, 50);
9601
9602 // Move back to original window.
9603 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009604 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009605 ADISPLAY_ID_DEFAULT, {50, 50}))
9606 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9607 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9608 mWindow->consumeDragEvent(false, 50, 50);
9609 mSecondWindow->consumeDragEvent(true, -50, 50);
9610
9611 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009612 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9613 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08009614 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9615 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9616 mWindow->assertNoEvents();
9617 mSecondWindow->assertNoEvents();
9618}
9619
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009620TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009621 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009622
9623 // No cancel event after drag start
9624 mSpyWindow->assertNoEvents();
9625
9626 const MotionEvent secondFingerDownEvent =
9627 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9628 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009629 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9630 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009631 .build();
9632 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009633 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009634 InputEventInjectionSync::WAIT_FOR_RESULT))
9635 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9636
9637 // Receives cancel for first pointer after next pointer down
9638 mSpyWindow->consumeMotionCancel();
9639 mSpyWindow->consumeMotionDown();
9640
9641 mSpyWindow->assertNoEvents();
9642}
9643
arthurhungf452d0b2021-01-06 00:19:52 +08009644TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009645 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08009646
9647 // Move on window.
9648 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009649 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009650 ADISPLAY_ID_DEFAULT, {50, 50}))
9651 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9652 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9653 mWindow->consumeDragEvent(false, 50, 50);
9654 mSecondWindow->assertNoEvents();
9655
9656 // Move to another window.
9657 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009658 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009659 ADISPLAY_ID_DEFAULT, {150, 50}))
9660 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9661 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9662 mWindow->consumeDragEvent(true, 150, 50);
9663 mSecondWindow->consumeDragEvent(false, 50, 50);
9664
9665 // drop to another window.
9666 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009667 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +08009668 {150, 50}))
9669 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9670 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009671 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08009672 mWindow->assertNoEvents();
9673 mSecondWindow->assertNoEvents();
9674}
9675
Vaibhav Devmurari110ba322023-11-17 10:47:16 +00009676TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
9677 startDrag();
9678
9679 // No cancel event after drag start
9680 mSpyWindow->assertNoEvents();
9681
9682 const MotionEvent secondFingerDownEvent =
9683 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9684 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
9685 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9686 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
9687 .build();
9688 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9689 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9690 InputEventInjectionSync::WAIT_FOR_RESULT))
9691 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9692
9693 // Receives cancel for first pointer after next pointer down
9694 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
9695 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9696 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
9697
9698 mSpyWindow->assertNoEvents();
9699
9700 // Spy window calls pilfer pointers
9701 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
9702 mDragWindow->assertNoEvents();
9703
9704 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -08009705 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +00009706 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
9707 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
9708 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
9709 .build();
9710 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -08009711 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +00009712 InputEventInjectionSync::WAIT_FOR_RESULT))
9713 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9714
9715 // Drag window should still receive the new event
9716 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
9717 mDragWindow->assertNoEvents();
9718}
9719
arthurhung6d4bed92021-03-17 11:59:33 +08009720TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009721 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08009722
9723 // Move on window and keep button pressed.
9724 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009725 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009726 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9727 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009728 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009729 .build()))
9730 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9731 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9732 mWindow->consumeDragEvent(false, 50, 50);
9733 mSecondWindow->assertNoEvents();
9734
9735 // Move to another window and release button, expect to drop item.
9736 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009737 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009738 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9739 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009740 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009741 .build()))
9742 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9743 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9744 mWindow->assertNoEvents();
9745 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009746 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08009747
9748 // nothing to the window.
9749 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009750 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009751 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
9752 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009753 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009754 .build()))
9755 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9756 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9757 mWindow->assertNoEvents();
9758 mSecondWindow->assertNoEvents();
9759}
9760
Arthur Hung54745652022-04-20 07:17:41 +00009761TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009762 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08009763
9764 // Set second window invisible.
9765 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009766 mDispatcher->onWindowInfosChanged(
9767 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +08009768
9769 // Move on window.
9770 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009771 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009772 ADISPLAY_ID_DEFAULT, {50, 50}))
9773 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9774 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9775 mWindow->consumeDragEvent(false, 50, 50);
9776 mSecondWindow->assertNoEvents();
9777
9778 // Move to another window.
9779 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009780 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009781 ADISPLAY_ID_DEFAULT, {150, 50}))
9782 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9783 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9784 mWindow->consumeDragEvent(true, 150, 50);
9785 mSecondWindow->assertNoEvents();
9786
9787 // drop to another window.
9788 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009789 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009790 {150, 50}))
9791 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9792 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009793 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08009794 mWindow->assertNoEvents();
9795 mSecondWindow->assertNoEvents();
9796}
9797
Arthur Hung54745652022-04-20 07:17:41 +00009798TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009799 // Ensure window could track pointerIds if it didn't support split touch.
9800 mWindow->setPreventSplitting(true);
9801
Arthur Hung54745652022-04-20 07:17:41 +00009802 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009803 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009804 {50, 50}))
9805 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9806 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9807
9808 const MotionEvent secondFingerDownEvent =
9809 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9810 .displayId(ADISPLAY_ID_DEFAULT)
9811 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009812 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9813 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009814 .build();
9815 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009816 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009817 InputEventInjectionSync::WAIT_FOR_RESULT))
9818 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009819 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00009820
9821 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009822 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009823}
9824
9825TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
9826 // First down on second window.
9827 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009828 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009829 {150, 50}))
9830 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9831
9832 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9833
9834 // Second down on first window.
9835 const MotionEvent secondFingerDownEvent =
9836 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9837 .displayId(ADISPLAY_ID_DEFAULT)
9838 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009839 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9840 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009841 .build();
9842 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009843 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009844 InputEventInjectionSync::WAIT_FOR_RESULT))
9845 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9846 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9847
9848 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009849 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009850
9851 // Move on window.
9852 const MotionEvent secondFingerMoveEvent =
9853 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9854 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009855 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9856 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009857 .build();
9858 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009859 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009860 InputEventInjectionSync::WAIT_FOR_RESULT));
9861 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9862 mWindow->consumeDragEvent(false, 50, 50);
9863 mSecondWindow->consumeMotionMove();
9864
9865 // Release the drag pointer should perform drop.
9866 const MotionEvent secondFingerUpEvent =
9867 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9868 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009869 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9870 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009871 .build();
9872 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009873 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009874 InputEventInjectionSync::WAIT_FOR_RESULT));
9875 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009876 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00009877 mWindow->assertNoEvents();
9878 mSecondWindow->consumeMotionMove();
9879}
9880
Arthur Hung3915c1f2022-05-31 07:17:17 +00009881TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009882 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00009883
9884 // Update window of second display.
9885 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009886 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009887 mDispatcher->onWindowInfosChanged(
9888 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9889 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9890 {},
9891 0,
9892 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009893
9894 // Let second display has a touch state.
9895 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009896 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009897 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9898 AINPUT_SOURCE_TOUCHSCREEN)
9899 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009900 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00009901 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009902 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00009903 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009904 mDispatcher->onWindowInfosChanged(
9905 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9906 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9907 {},
9908 0,
9909 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009910
9911 // Move on window.
9912 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009913 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009914 ADISPLAY_ID_DEFAULT, {50, 50}))
9915 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9916 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9917 mWindow->consumeDragEvent(false, 50, 50);
9918 mSecondWindow->assertNoEvents();
9919
9920 // Move to another window.
9921 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009922 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009923 ADISPLAY_ID_DEFAULT, {150, 50}))
9924 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9925 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9926 mWindow->consumeDragEvent(true, 150, 50);
9927 mSecondWindow->consumeDragEvent(false, 50, 50);
9928
9929 // drop to another window.
9930 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009931 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009932 {150, 50}))
9933 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9934 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009935 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00009936 mWindow->assertNoEvents();
9937 mSecondWindow->assertNoEvents();
9938}
9939
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009940TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
9941 startDrag(true, AINPUT_SOURCE_MOUSE);
9942 // Move on window.
9943 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009944 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009945 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9946 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009947 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009948 .x(50)
9949 .y(50))
9950 .build()))
9951 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9952 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9953 mWindow->consumeDragEvent(false, 50, 50);
9954 mSecondWindow->assertNoEvents();
9955
9956 // Move to another window.
9957 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009958 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009959 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9960 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009961 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009962 .x(150)
9963 .y(50))
9964 .build()))
9965 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9966 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9967 mWindow->consumeDragEvent(true, 150, 50);
9968 mSecondWindow->consumeDragEvent(false, 50, 50);
9969
9970 // drop to another window.
9971 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009972 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009973 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
9974 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009975 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009976 .x(150)
9977 .y(50))
9978 .build()))
9979 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9980 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009981 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009982 mWindow->assertNoEvents();
9983 mSecondWindow->assertNoEvents();
9984}
9985
Linnan Li5af92f92023-07-14 14:36:22 +08009986/**
9987 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
9988 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
9989 */
9990TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
9991 // Down on second window
9992 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9993 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9994 {150, 50}))
9995 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9996
9997 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
9998 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
9999
10000 // Down on first window
10001 const MotionEvent secondFingerDownEvent =
10002 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10003 .displayId(ADISPLAY_ID_DEFAULT)
10004 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10005 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10006 .build();
10007 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10008 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10009 InputEventInjectionSync::WAIT_FOR_RESULT))
10010 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10011 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10012 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
10013 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
10014
10015 // Start drag on first window
10016 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
10017
10018 // Trigger cancel
10019 mDispatcher->cancelCurrentTouch();
10020 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
10021 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
10022 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
10023
10024 ASSERT_TRUE(mDispatcher->waitForIdle());
10025 // The D&D finished with nullptr
10026 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
10027
10028 // Remove drag window
10029 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
10030
10031 // Inject a simple gesture, ensure dispatcher not crashed
10032 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10033 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10034 PointF{50, 50}))
10035 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10036 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10037
10038 const MotionEvent moveEvent =
10039 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10040 .displayId(ADISPLAY_ID_DEFAULT)
10041 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10042 .build();
10043 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10044 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
10045 InputEventInjectionSync::WAIT_FOR_RESULT))
10046 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10047 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
10048
10049 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10050 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10051 {50, 50}))
10052 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10053 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
10054}
10055
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000010056TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
10057 // Start hovering over the window.
10058 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10059 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
10060 ADISPLAY_ID_DEFAULT, {50, 50}));
10061
10062 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10063 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10064
10065 ASSERT_FALSE(startDrag(/*sendDown=*/false))
10066 << "Drag and drop should not work with a hovering pointer";
10067}
10068
Vishnu Nair062a8672021-09-03 16:07:44 -070010069class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
10070
10071TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
10072 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010073 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10074 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010075 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010076 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10077 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010078 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010079 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010080 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010081
10082 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010083 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010084 window->assertNoEvents();
10085
Prabir Pradhan678438e2023-04-13 19:32:51 +000010086 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10087 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010088 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10089 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080010090 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070010091 window->assertNoEvents();
10092
10093 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010094 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010095 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010096
Prabir Pradhan678438e2023-04-13 19:32:51 +000010097 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010098 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10099
Prabir Pradhan678438e2023-04-13 19:32:51 +000010100 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10101 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010102 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10103 window->assertNoEvents();
10104}
10105
10106TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
10107 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10108 std::make_shared<FakeApplicationHandle>();
10109 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010110 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10111 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010112 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010113 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010114 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010115 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010116 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10117 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010118 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010119 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010120 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10121 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010122 mDispatcher->onWindowInfosChanged(
10123 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010124 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010125 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010126
10127 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010128 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010129 window->assertNoEvents();
10130
Prabir Pradhan678438e2023-04-13 19:32:51 +000010131 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10132 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010133 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10134 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010135 window->assertNoEvents();
10136
10137 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010138 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010139 mDispatcher->onWindowInfosChanged(
10140 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010141
Prabir Pradhan678438e2023-04-13 19:32:51 +000010142 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010143 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10144
Prabir Pradhan678438e2023-04-13 19:32:51 +000010145 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10146 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010147 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
10148 window->assertNoEvents();
10149}
10150
10151TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
10152 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10153 std::make_shared<FakeApplicationHandle>();
10154 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010155 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10156 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010157 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010158 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010159 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010160 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010161 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10162 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010163 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010164 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010165 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10166 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010167 mDispatcher->onWindowInfosChanged(
10168 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010169 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010170 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010171
10172 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010173 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010174 window->assertNoEvents();
10175
Prabir Pradhan678438e2023-04-13 19:32:51 +000010176 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10177 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010178 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10179 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010180 window->assertNoEvents();
10181
10182 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010183 mDispatcher->onWindowInfosChanged(
10184 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010185
Prabir Pradhan678438e2023-04-13 19:32:51 +000010186 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010187 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10188
Prabir Pradhan678438e2023-04-13 19:32:51 +000010189 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10190 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010191 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10192 window->assertNoEvents();
10193}
10194
Antonio Kantekf16f2832021-09-28 04:39:20 +000010195class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
10196protected:
10197 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000010198 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010199 sp<FakeWindowHandle> mWindow;
10200 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000010201 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010202
10203 void SetUp() override {
10204 InputDispatcherTest::SetUp();
10205
10206 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000010207 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010208 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010209 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010210 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010211 mSecondWindow =
10212 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010213 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000010214 mThirdWindow =
10215 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
10216 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
10217 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010218
10219 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010220 mDispatcher->onWindowInfosChanged(
10221 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
10222 {},
10223 0,
10224 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000010225 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010226 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010227
Antonio Kantek15beb512022-06-13 22:35:41 +000010228 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010229 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010230 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070010231 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
10232 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010233 mThirdWindow->assertNoEvents();
10234 }
10235
10236 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
10237 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010238 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000010239 SECOND_DISPLAY_ID)) {
10240 mWindow->assertNoEvents();
10241 mSecondWindow->assertNoEvents();
10242 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070010243 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000010244 }
10245
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010246 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000010247 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070010248 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
10249 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010250 mWindow->consumeTouchModeEvent(inTouchMode);
10251 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010252 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000010253 }
10254};
10255
Antonio Kantek26defcf2022-02-08 01:12:27 +000010256TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010257 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000010258 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
10259 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010260 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010261}
10262
Antonio Kantek26defcf2022-02-08 01:12:27 +000010263TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
10264 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010265 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010266 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010267 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010268 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010269 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -070010270 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000010271 mWindow->assertNoEvents();
10272 mSecondWindow->assertNoEvents();
10273}
10274
10275TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
10276 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010277 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010278 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010279 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000010280 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010281 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010282}
10283
Antonio Kantekf16f2832021-09-28 04:39:20 +000010284TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010285 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000010286 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
10287 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010288 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010289 mWindow->assertNoEvents();
10290 mSecondWindow->assertNoEvents();
10291}
10292
Antonio Kantek15beb512022-06-13 22:35:41 +000010293TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
10294 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
10295 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10296 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010297 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000010298 mWindow->assertNoEvents();
10299 mSecondWindow->assertNoEvents();
10300 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
10301}
10302
Antonio Kantek48710e42022-03-24 14:19:30 -070010303TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
10304 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010305 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10306 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070010307 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10308 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
10309
10310 // Then remove focus.
10311 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010312 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070010313
10314 // Assert that caller can switch touch mode by owning one of the last interacted window.
10315 const WindowInfo& windowInfo = *mWindow->getInfo();
10316 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10317 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010318 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070010319}
10320
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010321class InputDispatcherSpyWindowTest : public InputDispatcherTest {
10322public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010323 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010324 std::shared_ptr<FakeApplicationHandle> application =
10325 std::make_shared<FakeApplicationHandle>();
10326 std::string name = "Fake Spy ";
10327 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010328 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
10329 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010330 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010331 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010332 return spy;
10333 }
10334
10335 sp<FakeWindowHandle> createForeground() {
10336 std::shared_ptr<FakeApplicationHandle> application =
10337 std::make_shared<FakeApplicationHandle>();
10338 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010339 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
10340 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010341 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010342 return window;
10343 }
10344
10345private:
10346 int mSpyCount{0};
10347};
10348
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010349using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010350/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010351 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
10352 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010353TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070010354 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010355 ScopedSilentDeath _silentDeath;
10356
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010357 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010358 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010359 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010360 ".* not a trusted overlay");
10361}
10362
10363/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010364 * Input injection into a display with a spy window but no foreground windows should succeed.
10365 */
10366TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010367 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010368 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010369
10370 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010371 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010372 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10373 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10374}
10375
10376/**
10377 * Verify the order in which different input windows receive events. The touched foreground window
10378 * (if there is one) should always receive the event first. When there are multiple spy windows, the
10379 * spy windows will receive the event according to their Z-order, where the top-most spy window will
10380 * receive events before ones belows it.
10381 *
10382 * Here, we set up a scenario with four windows in the following Z order from the top:
10383 * spy1, spy2, window, spy3.
10384 * We then inject an event and verify that the foreground "window" receives it first, followed by
10385 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
10386 * window.
10387 */
10388TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
10389 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010390 auto spy1 = createSpy();
10391 auto spy2 = createSpy();
10392 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010393 mDispatcher->onWindowInfosChanged(
10394 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010395 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
10396 const size_t numChannels = channels.size();
10397
Michael Wright8e9a8562022-02-09 13:44:29 +000010398 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010399 if (!epollFd.ok()) {
10400 FAIL() << "Failed to create epoll fd";
10401 }
10402
10403 for (size_t i = 0; i < numChannels; i++) {
10404 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
10405 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
10406 FAIL() << "Failed to add fd to epoll";
10407 }
10408 }
10409
10410 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010411 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010412 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10413
10414 std::vector<size_t> eventOrder;
10415 std::vector<struct epoll_event> events(numChannels);
10416 for (;;) {
10417 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
10418 (100ms).count());
10419 if (nFds < 0) {
10420 FAIL() << "Failed to call epoll_wait";
10421 }
10422 if (nFds == 0) {
10423 break; // epoll_wait timed out
10424 }
10425 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070010426 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070010427 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010428 channels[i]->consumeMotionDown();
10429 }
10430 }
10431
10432 // Verify the order in which the events were received.
10433 EXPECT_EQ(3u, eventOrder.size());
10434 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
10435 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
10436 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
10437}
10438
10439/**
10440 * A spy window using the NOT_TOUCHABLE flag does not receive events.
10441 */
10442TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
10443 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010444 auto spy = createSpy();
10445 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010446 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010447
10448 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010449 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010450 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10451 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10452 spy->assertNoEvents();
10453}
10454
10455/**
10456 * A spy window will only receive gestures that originate within its touchable region. Gestures that
10457 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
10458 * to the window.
10459 */
10460TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
10461 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010462 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010463 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010464 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010465
10466 // Inject an event outside the spy window's touchable region.
10467 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010468 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010469 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10470 window->consumeMotionDown();
10471 spy->assertNoEvents();
10472 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010473 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010474 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10475 window->consumeMotionUp();
10476 spy->assertNoEvents();
10477
10478 // Inject an event inside the spy window's touchable region.
10479 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010480 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010481 {5, 10}))
10482 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10483 window->consumeMotionDown();
10484 spy->consumeMotionDown();
10485}
10486
10487/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010488 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010489 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010490 */
10491TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
10492 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010493 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010494 auto spy = createSpy();
10495 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010496 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010497 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010498 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010499
10500 // Inject an event outside the spy window's frame and touchable region.
10501 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010502 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010503 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010504 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10505 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010506 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010507}
10508
10509/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010510 * Even when a spy window spans over multiple foreground windows, the spy should receive all
10511 * pointers that are down within its bounds.
10512 */
10513TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
10514 auto windowLeft = createForeground();
10515 windowLeft->setFrame({0, 0, 100, 200});
10516 auto windowRight = createForeground();
10517 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010518 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010519 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010520 mDispatcher->onWindowInfosChanged(
10521 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010522
10523 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010524 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010525 {50, 50}))
10526 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10527 windowLeft->consumeMotionDown();
10528 spy->consumeMotionDown();
10529
10530 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010531 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010532 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010533 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10534 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010535 .build();
10536 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010537 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010538 InputEventInjectionSync::WAIT_FOR_RESULT))
10539 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10540 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000010541 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010542}
10543
10544/**
10545 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
10546 * the spy should receive the second pointer with ACTION_DOWN.
10547 */
10548TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
10549 auto window = createForeground();
10550 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010551 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010552 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010553 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010554
10555 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010556 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010557 {50, 50}))
10558 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10559 window->consumeMotionDown();
10560 spyRight->assertNoEvents();
10561
10562 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010563 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010564 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010565 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10566 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010567 .build();
10568 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010569 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010570 InputEventInjectionSync::WAIT_FOR_RESULT))
10571 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010572 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010573 spyRight->consumeMotionDown();
10574}
10575
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010576/**
10577 * The spy window should not be able to affect whether or not touches are split. Only the foreground
10578 * windows should be allowed to control split touch.
10579 */
10580TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010581 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010582 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010583 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010584 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010585
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010586 auto window = createForeground();
10587 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010588
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010589 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010590
10591 // First finger down, no window touched.
10592 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010593 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010594 {100, 200}))
10595 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10596 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10597 window->assertNoEvents();
10598
10599 // Second finger down on window, the window should receive touch down.
10600 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010601 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010602 .displayId(ADISPLAY_ID_DEFAULT)
10603 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010604 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10605 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010606 .build();
10607 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010608 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010609 InputEventInjectionSync::WAIT_FOR_RESULT))
10610 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10611
10612 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000010613 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010614}
10615
10616/**
10617 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
10618 * do not receive key events.
10619 */
10620TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010621 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010622 spy->setFocusable(false);
10623
10624 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010625 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010626 setFocusedWindow(window);
10627 window->consumeFocusEvent(true);
10628
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010629 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010630 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10631 window->consumeKeyDown(ADISPLAY_ID_NONE);
10632
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010633 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010634 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10635 window->consumeKeyUp(ADISPLAY_ID_NONE);
10636
10637 spy->assertNoEvents();
10638}
10639
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010640using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
10641
10642/**
10643 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
10644 * are currently sent to any other windows - including other spy windows - will also be cancelled.
10645 */
10646TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
10647 auto window = createForeground();
10648 auto spy1 = createSpy();
10649 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010650 mDispatcher->onWindowInfosChanged(
10651 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010652
10653 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010654 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010655 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10656 window->consumeMotionDown();
10657 spy1->consumeMotionDown();
10658 spy2->consumeMotionDown();
10659
10660 // Pilfer pointers from the second spy window.
10661 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
10662 spy2->assertNoEvents();
10663 spy1->consumeMotionCancel();
10664 window->consumeMotionCancel();
10665
10666 // The rest of the gesture should only be sent to the second spy window.
10667 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010668 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010669 ADISPLAY_ID_DEFAULT))
10670 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10671 spy2->consumeMotionMove();
10672 spy1->assertNoEvents();
10673 window->assertNoEvents();
10674}
10675
10676/**
10677 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
10678 * in the middle of the gesture.
10679 */
10680TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
10681 auto window = createForeground();
10682 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010683 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010684
10685 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010686 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010687 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10688 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10689 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10690
10691 window->releaseChannel();
10692
10693 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10694
10695 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010696 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010697 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10698 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10699}
10700
10701/**
10702 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
10703 * the spy, but not to any other windows.
10704 */
10705TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
10706 auto spy = createSpy();
10707 auto window = createForeground();
10708
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010709 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010710
10711 // First finger down on the window and the spy.
10712 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010713 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010714 {100, 200}))
10715 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10716 spy->consumeMotionDown();
10717 window->consumeMotionDown();
10718
10719 // Spy window pilfers the pointers.
10720 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10721 window->consumeMotionCancel();
10722
10723 // Second finger down on the window and spy, but the window should not receive the pointer down.
10724 const MotionEvent secondFingerDownEvent =
10725 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10726 .displayId(ADISPLAY_ID_DEFAULT)
10727 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010728 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10729 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010730 .build();
10731 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010732 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010733 InputEventInjectionSync::WAIT_FOR_RESULT))
10734 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10735
Harry Cutts33476232023-01-30 19:57:29 +000010736 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010737
10738 // Third finger goes down outside all windows, so injection should fail.
10739 const MotionEvent thirdFingerDownEvent =
10740 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10741 .displayId(ADISPLAY_ID_DEFAULT)
10742 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010743 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10744 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10745 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010746 .build();
10747 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010748 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010749 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010750 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010751
10752 spy->assertNoEvents();
10753 window->assertNoEvents();
10754}
10755
10756/**
10757 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
10758 */
10759TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
10760 auto spy = createSpy();
10761 spy->setFrame(Rect(0, 0, 100, 100));
10762 auto window = createForeground();
10763 window->setFrame(Rect(0, 0, 200, 200));
10764
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010765 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010766
10767 // First finger down on the window only
10768 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010769 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010770 {150, 150}))
10771 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10772 window->consumeMotionDown();
10773
10774 // Second finger down on the spy and window
10775 const MotionEvent secondFingerDownEvent =
10776 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10777 .displayId(ADISPLAY_ID_DEFAULT)
10778 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010779 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10780 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010781 .build();
10782 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010783 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010784 InputEventInjectionSync::WAIT_FOR_RESULT))
10785 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10786 spy->consumeMotionDown();
10787 window->consumeMotionPointerDown(1);
10788
10789 // Third finger down on the spy and window
10790 const MotionEvent thirdFingerDownEvent =
10791 MotionEventBuilder(POINTER_2_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(150).y(150))
10795 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
10796 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010797 .build();
10798 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010799 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010800 InputEventInjectionSync::WAIT_FOR_RESULT))
10801 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10802 spy->consumeMotionPointerDown(1);
10803 window->consumeMotionPointerDown(2);
10804
10805 // Spy window pilfers the pointers.
10806 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000010807 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
10808 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010809
10810 spy->assertNoEvents();
10811 window->assertNoEvents();
10812}
10813
10814/**
10815 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
10816 * other windows should be canceled. If this results in the cancellation of all pointers for some
10817 * window, then that window should receive ACTION_CANCEL.
10818 */
10819TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
10820 auto spy = createSpy();
10821 spy->setFrame(Rect(0, 0, 100, 100));
10822 auto window = createForeground();
10823 window->setFrame(Rect(0, 0, 200, 200));
10824
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010825 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010826
10827 // First finger down on both spy and window
10828 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010829 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010830 {10, 10}))
10831 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10832 window->consumeMotionDown();
10833 spy->consumeMotionDown();
10834
10835 // Second finger down on the spy and window
10836 const MotionEvent secondFingerDownEvent =
10837 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10838 .displayId(ADISPLAY_ID_DEFAULT)
10839 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010840 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10841 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010842 .build();
10843 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010844 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010845 InputEventInjectionSync::WAIT_FOR_RESULT))
10846 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10847 spy->consumeMotionPointerDown(1);
10848 window->consumeMotionPointerDown(1);
10849
10850 // Spy window pilfers the pointers.
10851 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10852 window->consumeMotionCancel();
10853
10854 spy->assertNoEvents();
10855 window->assertNoEvents();
10856}
10857
10858/**
10859 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
10860 * be sent to other windows
10861 */
10862TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
10863 auto spy = createSpy();
10864 spy->setFrame(Rect(0, 0, 100, 100));
10865 auto window = createForeground();
10866 window->setFrame(Rect(0, 0, 200, 200));
10867
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010868 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010869
10870 // First finger down on both window and spy
10871 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010872 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010873 {10, 10}))
10874 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10875 window->consumeMotionDown();
10876 spy->consumeMotionDown();
10877
10878 // Spy window pilfers the pointers.
10879 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10880 window->consumeMotionCancel();
10881
10882 // Second finger down on the window only
10883 const MotionEvent secondFingerDownEvent =
10884 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10885 .displayId(ADISPLAY_ID_DEFAULT)
10886 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010887 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10888 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010889 .build();
10890 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010891 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010892 InputEventInjectionSync::WAIT_FOR_RESULT))
10893 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10894 window->consumeMotionDown();
10895 window->assertNoEvents();
10896
10897 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
10898 spy->consumeMotionMove();
10899 spy->assertNoEvents();
10900}
10901
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010902/**
10903 * A window on the left and a window on the right. Also, a spy window that's above all of the
10904 * windows, and spanning both left and right windows.
10905 * Send simultaneous motion streams from two different devices, one to the left window, and another
10906 * to the right window.
10907 * Pilfer from spy window.
10908 * Check that the pilfering only affects the pointers that are actually being received by the spy.
10909 */
10910TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
10911 sp<FakeWindowHandle> spy = createSpy();
10912 spy->setFrame(Rect(0, 0, 200, 200));
10913 sp<FakeWindowHandle> leftWindow = createForeground();
10914 leftWindow->setFrame(Rect(0, 0, 100, 100));
10915
10916 sp<FakeWindowHandle> rightWindow = createForeground();
10917 rightWindow->setFrame(Rect(100, 0, 200, 100));
10918
10919 constexpr int32_t stylusDeviceId = 1;
10920 constexpr int32_t touchDeviceId = 2;
10921
10922 mDispatcher->onWindowInfosChanged(
10923 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
10924
10925 // Stylus down on left window and spy
10926 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
10927 .deviceId(stylusDeviceId)
10928 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
10929 .build());
10930 leftWindow->consumeMotionEvent(
10931 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10932 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10933
10934 // Finger down on right window and spy - but spy already has stylus
10935 mDispatcher->notifyMotion(
10936 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10937 .deviceId(touchDeviceId)
10938 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
10939 .build());
10940 rightWindow->consumeMotionEvent(
10941 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010942 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010943
10944 // Act: pilfer from spy. Spy is currently receiving touch events.
10945 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010946 leftWindow->consumeMotionEvent(
10947 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010948 rightWindow->consumeMotionEvent(
10949 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
10950
10951 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
10952 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10953 .deviceId(stylusDeviceId)
10954 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
10955 .build());
10956 mDispatcher->notifyMotion(
10957 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10958 .deviceId(touchDeviceId)
10959 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
10960 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010961 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010962
10963 spy->assertNoEvents();
10964 leftWindow->assertNoEvents();
10965 rightWindow->assertNoEvents();
10966}
10967
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000010968TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
10969 auto window = createForeground();
10970 auto spy = createSpy();
10971 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
10972
10973 mDispatcher->notifyMotion(
10974 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
10975 .deviceId(1)
10976 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
10977 .build());
10978 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
10979 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
10980
10981 // Pilfer pointers from the spy window should fail.
10982 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
10983 spy->assertNoEvents();
10984 window->assertNoEvents();
10985}
10986
Prabir Pradhand65552b2021-10-07 11:23:50 -070010987class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
10988public:
10989 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
10990 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10991 std::make_shared<FakeApplicationHandle>();
10992 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010993 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10994 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010995 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010996 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010997 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010998 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010999 overlay->setTrustedOverlay(true);
11000
11001 std::shared_ptr<FakeApplicationHandle> application =
11002 std::make_shared<FakeApplicationHandle>();
11003 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011004 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
11005 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011006 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011007 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011008
11009 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011010 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011011 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011012 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011013 return {std::move(overlay), std::move(window)};
11014 }
11015
11016 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011017 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070011018 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000011019 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070011020 }
11021
11022 void sendStylusEvent(int32_t action) {
11023 NotifyMotionArgs motionArgs =
11024 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
11025 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011026 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000011027 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011028 }
11029};
11030
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011031using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
11032
11033TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070011034 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011035 ScopedSilentDeath _silentDeath;
11036
Prabir Pradhand65552b2021-10-07 11:23:50 -070011037 auto [overlay, window] = setupStylusOverlayScenario();
11038 overlay->setTrustedOverlay(false);
11039 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011040 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
11041 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070011042 ".* not a trusted overlay");
11043}
11044
11045TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
11046 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011047 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011048
11049 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11050 overlay->consumeMotionDown();
11051 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11052 overlay->consumeMotionUp();
11053
11054 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11055 window->consumeMotionDown();
11056 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11057 window->consumeMotionUp();
11058
11059 overlay->assertNoEvents();
11060 window->assertNoEvents();
11061}
11062
11063TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
11064 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011065 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011066 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011067
11068 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11069 overlay->consumeMotionDown();
11070 window->consumeMotionDown();
11071 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11072 overlay->consumeMotionUp();
11073 window->consumeMotionUp();
11074
11075 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11076 window->consumeMotionDown();
11077 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11078 window->consumeMotionUp();
11079
11080 overlay->assertNoEvents();
11081 window->assertNoEvents();
11082}
11083
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011084/**
11085 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
11086 * The scenario is as follows:
11087 * - The stylus interceptor overlay is configured as a spy window.
11088 * - The stylus interceptor spy receives the start of a new stylus gesture.
11089 * - It pilfers pointers and then configures itself to no longer be a spy.
11090 * - The stylus interceptor continues to receive the rest of the gesture.
11091 */
11092TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
11093 auto [overlay, window] = setupStylusOverlayScenario();
11094 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011095 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011096
11097 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11098 overlay->consumeMotionDown();
11099 window->consumeMotionDown();
11100
11101 // The interceptor pilfers the pointers.
11102 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
11103 window->consumeMotionCancel();
11104
11105 // The interceptor configures itself so that it is no longer a spy.
11106 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011107 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011108
11109 // It continues to receive the rest of the stylus gesture.
11110 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
11111 overlay->consumeMotionMove();
11112 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11113 overlay->consumeMotionUp();
11114
11115 window->assertNoEvents();
11116}
11117
Prabir Pradhan5735a322022-04-11 17:23:34 +000011118struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011119 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011120 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000011121 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
11122 std::unique_ptr<InputDispatcher>& mDispatcher;
11123
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011124 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000011125 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
11126
11127 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011128 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011129 ADISPLAY_ID_DEFAULT, {100, 200},
11130 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
11131 AMOTION_EVENT_INVALID_CURSOR_POSITION},
11132 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
11133 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
11134 }
11135
11136 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011137 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011138 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000011139 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000011140 mPolicyFlags);
11141 }
11142
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011143 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000011144 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11145 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011146 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11147 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000011148 window->setOwnerInfo(mPid, mUid);
11149 return window;
11150 }
11151};
11152
11153using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
11154
11155TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011156 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011157 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011158 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011159
11160 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11161 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11162 window->consumeMotionDown();
11163
11164 setFocusedWindow(window);
11165 window->consumeFocusEvent(true);
11166
11167 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11168 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11169 window->consumeKeyDown(ADISPLAY_ID_NONE);
11170}
11171
11172TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011173 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011174 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011175 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011176
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011177 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011178 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11179 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11180
11181 setFocusedWindow(window);
11182 window->consumeFocusEvent(true);
11183
11184 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11185 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11186 window->assertNoEvents();
11187}
11188
11189TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011190 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011191 auto window = owner.createWindow("Owned window");
11192 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011193 spy->setSpy(true);
11194 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011195 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011196
11197 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11198 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11199 spy->consumeMotionDown();
11200 window->consumeMotionDown();
11201}
11202
11203TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011204 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011205 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011206
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011207 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011208 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011209 randosSpy->setSpy(true);
11210 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011211 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011212
11213 // The event is targeted at owner's window, so injection should succeed, but the spy should
11214 // not receive the event.
11215 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11216 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11217 randosSpy->assertNoEvents();
11218 window->consumeMotionDown();
11219}
11220
11221TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011222 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011223 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011224
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011225 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011226 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011227 randosSpy->setSpy(true);
11228 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011229 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011230
11231 // A user that has injection permission can inject into any window.
11232 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011233 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011234 ADISPLAY_ID_DEFAULT));
11235 randosSpy->consumeMotionDown();
11236 window->consumeMotionDown();
11237
11238 setFocusedWindow(randosSpy);
11239 randosSpy->consumeFocusEvent(true);
11240
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011241 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000011242 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
11243 window->assertNoEvents();
11244}
11245
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011246TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011247 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011248 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011249
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011250 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011251 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011252 randosWindow->setFrame(Rect{-10, -10, -5, -5});
11253 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011254 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011255
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011256 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000011257 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11258 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11259 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011260 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000011261}
11262
Prabir Pradhan64f21d22023-11-28 21:19:42 +000011263using InputDispatcherPointerInWindowTest = InputDispatcherTest;
11264
11265TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
11266 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11267
11268 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11269 ADISPLAY_ID_DEFAULT);
11270 left->setFrame(Rect(0, 0, 100, 100));
11271 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11272 "Right Window", ADISPLAY_ID_DEFAULT);
11273 right->setFrame(Rect(100, 0, 200, 100));
11274 sp<FakeWindowHandle> spy =
11275 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
11276 spy->setFrame(Rect(0, 0, 200, 100));
11277 spy->setTrustedOverlay(true);
11278 spy->setSpy(true);
11279
11280 mDispatcher->onWindowInfosChanged(
11281 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
11282
11283 // Hover into the left window.
11284 mDispatcher->notifyMotion(
11285 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
11286 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
11287 .build());
11288
11289 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11290 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11291
11292 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11293 /*pointerId=*/0));
11294 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11295 /*pointerId=*/0));
11296 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11297 /*pointerId=*/0));
11298
11299 // Hover move to the right window.
11300 mDispatcher->notifyMotion(
11301 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
11302 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
11303 .build());
11304
11305 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11306 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11307 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
11308
11309 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11310 /*pointerId=*/0));
11311 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11312 /*pointerId=*/0));
11313 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11314 /*pointerId=*/0));
11315
11316 // Stop hovering.
11317 mDispatcher->notifyMotion(
11318 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
11319 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
11320 .build());
11321
11322 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11323 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11324
11325 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11326 /*pointerId=*/0));
11327 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11328 /*pointerId=*/0));
11329 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11330 /*pointerId=*/0));
11331}
11332
11333TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
11334 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11335
11336 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11337 ADISPLAY_ID_DEFAULT);
11338 left->setFrame(Rect(0, 0, 100, 100));
11339 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11340 "Right Window", ADISPLAY_ID_DEFAULT);
11341 right->setFrame(Rect(100, 0, 200, 100));
11342 sp<FakeWindowHandle> spy =
11343 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
11344 spy->setFrame(Rect(0, 0, 200, 100));
11345 spy->setTrustedOverlay(true);
11346 spy->setSpy(true);
11347
11348 mDispatcher->onWindowInfosChanged(
11349 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
11350
11351 // First pointer down on left window.
11352 mDispatcher->notifyMotion(
11353 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11354 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11355 .build());
11356
11357 left->consumeMotionDown();
11358 spy->consumeMotionDown();
11359
11360 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11361 /*pointerId=*/0));
11362 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11363 /*pointerId=*/0));
11364 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11365 /*pointerId=*/0));
11366
11367 // Second pointer down on right window.
11368 mDispatcher->notifyMotion(
11369 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11370 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11371 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
11372 .build());
11373
11374 left->consumeMotionMove();
11375 right->consumeMotionDown();
11376 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
11377
11378 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11379 /*pointerId=*/0));
11380 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11381 /*pointerId=*/0));
11382 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11383 /*pointerId=*/0));
11384 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11385 /*pointerId=*/1));
11386 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11387 /*pointerId=*/1));
11388 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11389 /*pointerId=*/1));
11390
11391 // Second pointer up.
11392 mDispatcher->notifyMotion(
11393 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
11394 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11395 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
11396 .build());
11397
11398 left->consumeMotionMove();
11399 right->consumeMotionUp();
11400 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
11401
11402 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11403 /*pointerId=*/0));
11404 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11405 /*pointerId=*/0));
11406 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11407 /*pointerId=*/0));
11408 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11409 /*pointerId=*/1));
11410 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11411 /*pointerId=*/1));
11412 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11413 /*pointerId=*/1));
11414
11415 // First pointer up.
11416 mDispatcher->notifyMotion(
11417 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
11418 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11419 .build());
11420
11421 left->consumeMotionUp();
11422 spy->consumeMotionUp();
11423
11424 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11425 /*pointerId=*/0));
11426 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11427 /*pointerId=*/0));
11428 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11429 /*pointerId=*/0));
11430}
11431
11432TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
11433 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11434
11435 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11436 ADISPLAY_ID_DEFAULT);
11437 left->setFrame(Rect(0, 0, 100, 100));
11438 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11439 "Right Window", ADISPLAY_ID_DEFAULT);
11440 right->setFrame(Rect(100, 0, 200, 100));
11441
11442 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
11443
11444 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11445 /*pointerId=*/0));
11446 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11447 /*pointerId=*/0));
11448
11449 // Hover move into the window.
11450 mDispatcher->notifyMotion(
11451 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11452 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
11453 .rawXCursorPosition(50)
11454 .rawYCursorPosition(50)
11455 .deviceId(DEVICE_ID)
11456 .build());
11457
11458 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11459
11460 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11461 /*pointerId=*/0));
11462
11463 // Move the mouse with another device. This cancels the hovering pointer from the first device.
11464 mDispatcher->notifyMotion(
11465 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11466 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
11467 .rawXCursorPosition(51)
11468 .rawYCursorPosition(50)
11469 .deviceId(SECOND_DEVICE_ID)
11470 .build());
11471
11472 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11473 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11474
11475 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
11476 // a HOVER_EXIT from the first device.
11477 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11478 /*pointerId=*/0));
11479 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
11480 SECOND_DEVICE_ID,
11481 /*pointerId=*/0));
11482
11483 // Move the mouse outside the window. Document the current behavior, where the window does not
11484 // receive HOVER_EXIT even though the mouse left the window.
11485 mDispatcher->notifyMotion(
11486 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11487 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
11488 .rawXCursorPosition(150)
11489 .rawYCursorPosition(50)
11490 .deviceId(SECOND_DEVICE_ID)
11491 .build());
11492
11493 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11494 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11495 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11496 /*pointerId=*/0));
11497 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
11498 SECOND_DEVICE_ID,
11499 /*pointerId=*/0));
11500}
11501
Garfield Tane84e6f92019-08-29 17:28:41 -070011502} // namespace android::inputdispatcher