blob: 6abaa55d92a785443fb0f23225c5e1931c12b950 [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
Yeabkal Wubshit88a90412023-12-21 18:23:04 -0800552 void interceptMotionBeforeQueueing(int32_t, uint32_t, 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,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001096 int32_t displayId, bool createInputChannel = true)
chaviwd1c23182019-12-20 18:44:56 -08001097 : mName(name) {
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001098 sp<IBinder> token;
1099 if (createInputChannel) {
Garfield Tan15601662020-09-22 15:32:38 -07001100 base::Result<std::unique_ptr<InputChannel>> channel =
1101 dispatcher->createInputChannel(name);
1102 token = (*channel)->getConnectionToken();
1103 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001104 }
1105
1106 inputApplicationHandle->updateInfo();
1107 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1108
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001109 mInfo.token = token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001110 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001111 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001112 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001113 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001114 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001115 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001116 mInfo.globalScaleFactor = 1.0;
1117 mInfo.touchableRegion.clear();
1118 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001119 mInfo.ownerPid = WINDOW_PID;
1120 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001121 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001122 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001123 }
1124
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001125 sp<FakeWindowHandle> clone(int32_t displayId) {
1126 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1127 handle->mInfo = mInfo;
1128 handle->mInfo.displayId = displayId;
1129 handle->mInfo.id = sId++;
1130 handle->mInputReceiver = mInputReceiver;
1131 return handle;
1132 }
1133
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001134 void setTouchable(bool touchable) {
1135 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1136 }
chaviwd1c23182019-12-20 18:44:56 -08001137
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001138 void setFocusable(bool focusable) {
1139 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1140 }
1141
1142 void setVisible(bool visible) {
1143 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1144 }
Vishnu Nair958da932020-08-21 17:12:37 -07001145
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001146 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001147 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001148 }
1149
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001150 void setPaused(bool paused) {
1151 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1152 }
1153
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001154 void setPreventSplitting(bool preventSplitting) {
1155 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001156 }
1157
1158 void setSlippery(bool slippery) {
1159 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1160 }
1161
1162 void setWatchOutsideTouch(bool watchOutside) {
1163 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1164 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001165
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001166 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1167
1168 void setInterceptsStylus(bool interceptsStylus) {
1169 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1170 }
1171
1172 void setDropInput(bool dropInput) {
1173 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1174 }
1175
1176 void setDropInputIfObscured(bool dropInputIfObscured) {
1177 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1178 }
1179
1180 void setNoInputChannel(bool noInputChannel) {
1181 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1182 }
1183
Josep del Riob3981622023-04-18 15:49:45 +00001184 void setDisableUserActivity(bool disableUserActivity) {
1185 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1186 }
1187
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07001188 void setGlobalStylusBlocksTouch(bool shouldGlobalStylusBlockTouch) {
1189 mInfo.setInputConfig(WindowInfo::InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH,
1190 shouldGlobalStylusBlockTouch);
1191 }
1192
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001193 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1194
chaviw3277faf2021-05-19 16:45:23 -05001195 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001196
Bernardo Rufino7393d172021-02-26 13:56:11 +00001197 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1198
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001199 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001200 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001201 mInfo.touchableRegion.clear();
1202 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001203
1204 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1205 ui::Transform translate;
1206 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1207 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001208 }
1209
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001210 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1211
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001212 void setIsWallpaper(bool isWallpaper) {
1213 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1214 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001215
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001216 void setDupTouchToWallpaper(bool hasWallpaper) {
1217 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1218 }
chaviwd1c23182019-12-20 18:44:56 -08001219
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001220 void setTrustedOverlay(bool trustedOverlay) {
1221 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1222 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001223
chaviw9eaa22c2020-07-01 16:21:27 -07001224 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1225 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1226 }
1227
1228 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001229
yunho.shinf4a80b82020-11-16 21:13:57 +09001230 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1231
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001232 const KeyEvent& consumeKey(bool handled = true) {
1233 const InputEvent& event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED, handled);
1234 if (event.getType() != InputEventType::KEY) {
1235 LOG(FATAL) << "Instead of key event, got " << event;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001236 }
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001237 return static_cast<const KeyEvent&>(event);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001238 }
1239
1240 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001241 const KeyEvent& keyEvent = consumeKey();
1242 ASSERT_THAT(keyEvent, matcher);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001243 }
1244
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001245 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001246 consumeKeyEvent(AllOf(WithKeyAction(ACTION_DOWN), WithDisplayId(expectedDisplayId),
1247 WithFlags(expectedFlags)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001248 }
1249
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001250 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001251 consumeKeyEvent(AllOf(WithKeyAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1252 WithFlags(expectedFlags)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001253 }
1254
Svet Ganov5d3bc372020-01-26 23:11:07 -08001255 void consumeMotionCancel(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(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1258 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001259 }
1260
1261 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001262 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001263 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1264 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001265 }
1266
1267 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001268 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001269 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1270 }
1271
1272 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1273 std::optional<int32_t> expectedFlags = std::nullopt) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001274 consumeMotionEvent(
1275 AllOf(WithMotionAction(ACTION_DOWN),
1276 testing::Conditional(expectedDisplayId.has_value(),
1277 WithDisplayId(*expectedDisplayId), testing::_),
1278 testing::Conditional(expectedFlags.has_value(), WithFlags(*expectedFlags),
1279 testing::_)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001280 }
1281
Svet Ganov5d3bc372020-01-26 23:11:07 -08001282 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001283 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1284 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001285 const int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001286 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001287 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1288 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001289 }
1290
1291 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001292 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001293 const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001294 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001295 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1296 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001297 }
1298
1299 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001300 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001301 consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1302 WithFlags(expectedFlags)));
Michael Wright3a240c42019-12-10 20:53:41 +00001303 }
1304
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001305 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1306 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001307 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE),
1308 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001309 }
1310
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001311 void consumeMotionOutsideWithZeroedCoords() {
1312 consumeMotionEvent(
1313 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE), WithRawCoords(0, 0)));
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001314 }
1315
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001316 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1317 ASSERT_NE(mInputReceiver, nullptr)
1318 << "Cannot consume events from a window with no receiver";
1319 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1320 }
1321
Prabir Pradhan99987712020-11-10 18:43:05 -08001322 void consumeCaptureEvent(bool hasCapture) {
1323 ASSERT_NE(mInputReceiver, nullptr)
1324 << "Cannot consume events from a window with no receiver";
1325 mInputReceiver->consumeCaptureEvent(hasCapture);
1326 }
1327
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001328 const MotionEvent& consumeMotionEvent(
1329 const ::testing::Matcher<MotionEvent>& matcher = testing::_) {
1330 const InputEvent& event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
1331 if (event.getType() != InputEventType::MOTION) {
1332 LOG(FATAL) << "Instead of motion event, got " << event;
Prabir Pradhan5893d362023-11-17 04:30:40 +00001333 }
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001334 const auto& motionEvent = static_cast<const MotionEvent&>(event);
1335 EXPECT_THAT(motionEvent, matcher);
1336 return motionEvent;
chaviwd1c23182019-12-20 18:44:56 -08001337 }
1338
arthurhungb89ccb02020-12-30 16:19:01 +08001339 void consumeDragEvent(bool isExiting, float x, float y) {
1340 mInputReceiver->consumeDragEvent(isExiting, x, y);
1341 }
1342
Antonio Kantekf16f2832021-09-28 04:39:20 +00001343 void consumeTouchModeEvent(bool inTouchMode) {
1344 ASSERT_NE(mInputReceiver, nullptr)
1345 << "Cannot consume events from a window with no receiver";
1346 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1347 }
1348
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001349 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001350 if (mInputReceiver == nullptr) {
1351 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1352 return std::nullopt;
1353 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001354 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED, outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001355 }
1356
1357 void finishEvent(uint32_t sequenceNum) {
1358 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1359 mInputReceiver->finishEvent(sequenceNum);
1360 }
1361
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001362 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1363 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1364 mInputReceiver->sendTimeline(inputEventId, timeline);
1365 }
1366
Arthur Hungb92218b2018-08-14 12:00:21 +08001367 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001368 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001369 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001370 return; // Can't receive events if the window does not have input channel
1371 }
1372 ASSERT_NE(nullptr, mInputReceiver)
1373 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001374 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001375 }
1376
chaviwaf87b3e2019-10-01 16:59:28 -07001377 sp<IBinder> getToken() { return mInfo.token; }
1378
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001379 const std::string& getName() { return mName; }
1380
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001381 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001382 mInfo.ownerPid = ownerPid;
1383 mInfo.ownerUid = ownerUid;
1384 }
1385
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001386 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001387
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001388 void destroyReceiver() { mInputReceiver = nullptr; }
1389
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001390 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1391
chaviwd1c23182019-12-20 18:44:56 -08001392private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001393 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001394 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001395 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001396 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001397 friend class sp<FakeWindowHandle>;
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001398
1399 const InputEvent& consume(std::chrono::milliseconds timeout, bool handled = true) {
1400 if (mInputReceiver == nullptr) {
1401 LOG(FATAL) << "Cannot consume event from a window with no input event receiver";
1402 }
1403 InputEvent* event = mInputReceiver->consume(timeout, handled);
1404 if (event == nullptr) {
1405 LOG(FATAL) << "Consume failed: no event";
1406 }
1407 return *event;
1408 }
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001409};
1410
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001411std::atomic<int32_t> FakeWindowHandle::sId{1};
1412
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001413class FakeMonitorReceiver {
1414public:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001415 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId)
1416 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001417
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001418 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001419
1420 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001421 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1422 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001423 }
1424
1425 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001426 return mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001427 }
1428
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001429 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001430
1431 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001432 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1433 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001434 }
1435
1436 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001437 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1438 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001439 }
1440
1441 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001442 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1443 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001444 }
1445
1446 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001447 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001448 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1449 WithDisplayId(expectedDisplayId),
1450 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1451 }
1452
1453 void consumeMotionPointerDown(int32_t pointerIdx) {
1454 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1455 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001456 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1457 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001458 }
1459
1460 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001461 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001462 }
1463
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001464 MotionEvent* consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001465
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001466 void assertNoEvents() { mInputReceiver.assertNoEvents(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001467
1468private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001469 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001470};
1471
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001472static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001473 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001474 int32_t displayId = ADISPLAY_ID_NONE,
1475 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001476 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001477 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001478 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001479 KeyEvent event;
1480 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1481
1482 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001483 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001484 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1485 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001486
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001487 if (!allowKeyRepeat) {
1488 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1489 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001490 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001491 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001492}
1493
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001494static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1495 InputEventInjectionResult result =
1496 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1497 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1498 if (result != InputEventInjectionResult::TIMED_OUT) {
1499 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1500 }
1501}
1502
1503static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001504 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001505 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001506}
1507
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001508// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1509// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1510// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001511static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1512 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001513 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001514 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001515 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001516}
1517
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001518static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001519 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001520 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001521}
1522
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001523static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001524 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001525 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001526 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001527 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001528 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1529 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001530}
1531
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001532static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001533 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1534 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001535 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001536 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1537 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001538 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001539 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001540 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001541 MotionEventBuilder motionBuilder =
1542 MotionEventBuilder(action, source)
1543 .displayId(displayId)
1544 .eventTime(eventTime)
1545 .rawXCursorPosition(cursorPosition.x)
1546 .rawYCursorPosition(cursorPosition.y)
1547 .pointer(
1548 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1549 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1550 motionBuilder.downTime(eventTime);
1551 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001552
1553 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001554 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1555 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001556}
1557
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001558static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1559 int32_t displayId,
1560 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001561 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001562}
1563
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001564static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1565 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001566 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001567 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001568}
1569
Jackal Guof9696682018-10-05 12:23:23 +08001570static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1571 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1572 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001573 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1574 AINPUT_SOURCE_KEYBOARD, displayId, POLICY_FLAG_PASS_TO_USER, action,
1575 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001576
1577 return args;
1578}
1579
Josep del Riob3981622023-04-18 15:49:45 +00001580static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1581 int32_t displayId = ADISPLAY_ID_NONE) {
1582 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1583 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001584 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1585 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C,
1586 AMETA_META_ON, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001587
1588 return args;
1589}
1590
1591static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1592 int32_t displayId = ADISPLAY_ID_NONE) {
1593 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1594 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001595 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1596 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST,
1597 KEY_ASSISTANT, AMETA_NONE, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001598
1599 return args;
1600}
1601
Prabir Pradhan678438e2023-04-13 19:32:51 +00001602[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1603 int32_t displayId,
1604 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001605 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001606 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1607 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1608 }
1609
chaviwd1c23182019-12-20 18:44:56 -08001610 PointerProperties pointerProperties[pointerCount];
1611 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001612
chaviwd1c23182019-12-20 18:44:56 -08001613 for (size_t i = 0; i < pointerCount; i++) {
1614 pointerProperties[i].clear();
1615 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001616 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001617
chaviwd1c23182019-12-20 18:44:56 -08001618 pointerCoords[i].clear();
1619 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1620 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1621 }
Jackal Guof9696682018-10-05 12:23:23 +08001622
1623 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1624 // Define a valid motion event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001625 NotifyMotionArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, source,
1626 displayId, POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0,
1627 /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001628 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001629 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001630 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001631 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001632
1633 return args;
1634}
1635
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001636static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1637 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1638}
1639
chaviwd1c23182019-12-20 18:44:56 -08001640static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1641 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1642}
1643
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001644static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1645 const PointerCaptureRequest& request) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001646 return NotifyPointerCaptureChangedArgs(InputEvent::nextId(), systemTime(SYSTEM_TIME_MONOTONIC),
1647 request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001648}
1649
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001650} // namespace
1651
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001652/**
1653 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1654 * broken channel.
1655 */
1656TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1657 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1658 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001659 sp<FakeWindowHandle>::make(application, mDispatcher,
1660 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001661
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001662 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001663
1664 // Window closes its channel, but the window remains.
1665 window->destroyReceiver();
1666 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1667}
1668
Arthur Hungb92218b2018-08-14 12:00:21 +08001669TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001670 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001671 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1672 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001673
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001674 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001675 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001676 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001677 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001678
1679 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001680 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001681}
1682
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001683TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1684 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001685 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1686 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001687
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001688 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001689 // Inject a MotionEvent to an unknown display.
1690 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001691 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001692 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1693
1694 // Window should receive motion event.
1695 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1696}
1697
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001698/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001699 * Calling onWindowInfosChanged once should not cause any issues.
1700 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001701 * called twice.
1702 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001703TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001704 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001705 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1706 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001707 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001708
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001709 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001710 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001711 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001712 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001713 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001714
1715 // Window should receive motion event.
1716 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1717}
1718
1719/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001720 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001721 */
1722TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001723 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001724 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1725 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001726 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001727
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001728 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1729 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001730 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001731 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001732 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001733 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001734
1735 // Window should receive motion event.
1736 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1737}
1738
Arthur Hungb92218b2018-08-14 12:00:21 +08001739// The foreground window should receive the first touch down event.
1740TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001741 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001742 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001743 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001744 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001745 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001746
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001747 mDispatcher->onWindowInfosChanged(
1748 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001749 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001750 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001751 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001752
1753 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001754 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001755 windowSecond->assertNoEvents();
1756}
1757
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001758/**
1759 * Two windows: A top window, and a wallpaper behind the window.
1760 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1761 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001762 * 1. foregroundWindow <-- dup touch to wallpaper
1763 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001764 */
1765TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1766 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1767 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001768 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001769 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001770 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001771 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001772 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001773
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001774 mDispatcher->onWindowInfosChanged(
1775 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001776 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001777 injectMotionEvent(*mDispatcher,
1778 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1779 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
1780 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001781 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1782
1783 // Both foreground window and its wallpaper should receive the touch down
1784 foregroundWindow->consumeMotionDown();
1785 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1786
1787 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001788 injectMotionEvent(*mDispatcher,
1789 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1790 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
1791 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001792 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1793
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001794 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001795 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1796
1797 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001798 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001799 foregroundWindow->consumeMotionCancel();
1800 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1801 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1802}
1803
1804/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001805 * Two fingers down on the window, and lift off the first finger.
1806 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1807 * contains a single pointer.
1808 */
1809TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1810 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1811 sp<FakeWindowHandle> window =
1812 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1813
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001814 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001815 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001816 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1817 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1818 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001819 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001820 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1821 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1822 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1823 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001824 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001825 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1826 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1827 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1828 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001829 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1830 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1831 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1832
1833 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001834 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001835 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1836 window->consumeMotionEvent(
1837 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1838}
1839
1840/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001841 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1842 * with the following differences:
1843 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1844 * clean up the connection.
1845 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1846 * Ensure that there's no crash in the dispatcher.
1847 */
1848TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1849 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1850 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001851 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001852 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001853 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001854 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001855 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001856
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001857 mDispatcher->onWindowInfosChanged(
1858 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001859 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001860 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001861 {100, 200}))
1862 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1863
1864 // Both foreground window and its wallpaper should receive the touch down
1865 foregroundWindow->consumeMotionDown();
1866 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1867
1868 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001869 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001870 ADISPLAY_ID_DEFAULT, {110, 200}))
1871 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1872
1873 foregroundWindow->consumeMotionMove();
1874 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1875
1876 // Wallpaper closes its channel, but the window remains.
1877 wallpaperWindow->destroyReceiver();
1878 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1879
1880 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1881 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001882 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001883 foregroundWindow->consumeMotionCancel();
1884}
1885
Arthur Hungc539dbb2022-12-08 07:45:36 +00001886class ShouldSplitTouchFixture : public InputDispatcherTest,
1887 public ::testing::WithParamInterface<bool> {};
1888INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1889 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001890/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001891 * A single window that receives touch (on top), and a wallpaper window underneath it.
1892 * The top window gets a multitouch gesture.
1893 * Ensure that wallpaper gets the same gesture.
1894 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001895TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001896 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001897 sp<FakeWindowHandle> foregroundWindow =
1898 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1899 foregroundWindow->setDupTouchToWallpaper(true);
1900 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001901
1902 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001903 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001904 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001905
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001906 mDispatcher->onWindowInfosChanged(
1907 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001908
1909 // Touch down on top window
1910 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001911 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001912 {100, 100}))
1913 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1914
1915 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001916 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001917 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1918
1919 // Second finger down on the top window
1920 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001921 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001922 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001923 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1924 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001925 .build();
1926 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001927 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001928 InputEventInjectionSync::WAIT_FOR_RESULT))
1929 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1930
Harry Cutts33476232023-01-30 19:57:29 +00001931 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1932 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001933 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001934
1935 const MotionEvent secondFingerUpEvent =
1936 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1937 .displayId(ADISPLAY_ID_DEFAULT)
1938 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001939 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1940 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001941 .build();
1942 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001943 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001944 InputEventInjectionSync::WAIT_FOR_RESULT))
1945 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1946 foregroundWindow->consumeMotionPointerUp(0);
1947 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1948
1949 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001950 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001951 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1952 AINPUT_SOURCE_TOUCHSCREEN)
1953 .displayId(ADISPLAY_ID_DEFAULT)
1954 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001955 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001956 .x(100)
1957 .y(100))
1958 .build(),
1959 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001960 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1961 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1962 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001963}
1964
1965/**
1966 * Two windows: a window on the left and window on the right.
1967 * A third window, wallpaper, is behind both windows, and spans both top windows.
1968 * The first touch down goes to the left window. A second pointer touches down on the right window.
1969 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1970 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1971 * ACTION_POINTER_DOWN(1).
1972 */
1973TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1974 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1975 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001976 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001977 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001978 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001979
1980 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001981 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001982 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001983 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001984
1985 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001986 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001987 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001988 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001989
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001990 mDispatcher->onWindowInfosChanged(
1991 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1992 {},
1993 0,
1994 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001995
1996 // Touch down on left window
1997 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001998 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001999 {100, 100}))
2000 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2001
2002 // Both foreground window and its wallpaper should receive the touch down
2003 leftWindow->consumeMotionDown();
2004 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2005
2006 // Second finger down on the right window
2007 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002008 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002009 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002010 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2011 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002012 .build();
2013 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002014 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002015 InputEventInjectionSync::WAIT_FOR_RESULT))
2016 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2017
2018 leftWindow->consumeMotionMove();
2019 // Since the touch is split, right window gets ACTION_DOWN
2020 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002021 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002022 expectedWallpaperFlags);
2023
2024 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002025 mDispatcher->onWindowInfosChanged(
2026 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002027 leftWindow->consumeMotionCancel();
2028 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2029 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2030
2031 // The pointer that's still down on the right window moves, and goes to the right window only.
2032 // As far as the dispatcher's concerned though, both pointers are still present.
2033 const MotionEvent secondFingerMoveEvent =
2034 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2035 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002036 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2037 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002038 .build();
2039 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002040 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002041 InputEventInjectionSync::WAIT_FOR_RESULT));
2042 rightWindow->consumeMotionMove();
2043
2044 leftWindow->assertNoEvents();
2045 rightWindow->assertNoEvents();
2046 wallpaperWindow->assertNoEvents();
2047}
2048
Arthur Hungc539dbb2022-12-08 07:45:36 +00002049/**
2050 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2051 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2052 * The right window should receive ACTION_DOWN.
2053 */
2054TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002055 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002056 sp<FakeWindowHandle> leftWindow =
2057 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2058 leftWindow->setFrame(Rect(0, 0, 200, 200));
2059 leftWindow->setDupTouchToWallpaper(true);
2060 leftWindow->setSlippery(true);
2061
2062 sp<FakeWindowHandle> rightWindow =
2063 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2064 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002065
2066 sp<FakeWindowHandle> wallpaperWindow =
2067 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2068 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002069
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002070 mDispatcher->onWindowInfosChanged(
2071 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2072 {},
2073 0,
2074 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002075
Arthur Hungc539dbb2022-12-08 07:45:36 +00002076 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002077 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002078 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002079 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002080 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002081
2082 // Both foreground window and its wallpaper should receive the touch down
2083 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002084 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2085
Arthur Hungc539dbb2022-12-08 07:45:36 +00002086 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002087 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002088 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002089 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002090 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2091
Arthur Hungc539dbb2022-12-08 07:45:36 +00002092 leftWindow->consumeMotionCancel();
2093 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2094 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002095}
2096
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002097/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002098 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2099 * interactive, it might stop sending this flag.
2100 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2101 * to have a consistent input stream.
2102 *
2103 * Test procedure:
2104 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2105 * DOWN (new gesture).
2106 *
2107 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2108 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2109 *
2110 * We technically just need a single window here, but we are using two windows (spy on top and a
2111 * regular window below) to emulate the actual situation where it happens on the device.
2112 */
2113TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2114 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2115 sp<FakeWindowHandle> spyWindow =
2116 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2117 spyWindow->setFrame(Rect(0, 0, 200, 200));
2118 spyWindow->setTrustedOverlay(true);
2119 spyWindow->setSpy(true);
2120
2121 sp<FakeWindowHandle> window =
2122 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2123 window->setFrame(Rect(0, 0, 200, 200));
2124
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002125 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002126 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002127
2128 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002129 mDispatcher->notifyMotion(
2130 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2131 .deviceId(touchDeviceId)
2132 .policyFlags(DEFAULT_POLICY_FLAGS)
2133 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2134 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002135
Prabir Pradhan678438e2023-04-13 19:32:51 +00002136 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2137 .deviceId(touchDeviceId)
2138 .policyFlags(DEFAULT_POLICY_FLAGS)
2139 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2140 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2141 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002142 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2143 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2144 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2145 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2146
2147 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002148 mDispatcher->notifyMotion(
2149 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2150 .deviceId(touchDeviceId)
2151 .policyFlags(0)
2152 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2153 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2154 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002155 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2156 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2157
2158 // We don't need to reset the device to reproduce the issue, but the reset event typically
2159 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002160 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002161
2162 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002163 mDispatcher->notifyMotion(
2164 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2165 .deviceId(touchDeviceId)
2166 .policyFlags(DEFAULT_POLICY_FLAGS)
2167 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2168 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002169 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2170 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2171
2172 // No more events
2173 spyWindow->assertNoEvents();
2174 window->assertNoEvents();
2175}
2176
2177/**
Linnan Li907ae732023-09-05 17:14:21 +08002178 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
2179 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2180 * interactive, it might stop sending this flag.
2181 * We've already ensured the consistency of the touch event in this case, and we should also ensure
2182 * the consistency of the hover event in this case.
2183 *
2184 * Test procedure:
2185 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
2186 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
2187 *
2188 * We expect to receive two full streams of hover events.
2189 */
2190TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
2191 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2192
2193 sp<FakeWindowHandle> window =
2194 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2195 window->setFrame(Rect(0, 0, 300, 300));
2196
2197 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2198
2199 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2200 .policyFlags(DEFAULT_POLICY_FLAGS)
2201 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2202 .build());
2203 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2204
2205 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2206 .policyFlags(DEFAULT_POLICY_FLAGS)
2207 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2208 .build());
2209 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2210
2211 // Send hover exit without the default policy flags.
2212 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2213 .policyFlags(0)
2214 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2215 .build());
2216
2217 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2218
2219 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
2220 // right event.
2221 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2222 .policyFlags(DEFAULT_POLICY_FLAGS)
2223 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
2224 .build());
2225 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2226
2227 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, 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_MOVE));
2232
2233 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2234 .policyFlags(DEFAULT_POLICY_FLAGS)
2235 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2236 .build());
2237 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2238}
2239
2240/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002241 * Two windows: a window on the left and a window on the right.
2242 * Mouse is hovered from the right window into the left window.
2243 * Next, we tap on the left window, where the cursor was last seen.
2244 * The second tap is done onto the right window.
2245 * The mouse and tap are from two different devices.
2246 * We technically don't need to set the downtime / eventtime for these events, but setting these
2247 * explicitly helps during debugging.
2248 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2249 * In the buggy implementation, a tap on the right window would cause a crash.
2250 */
2251TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2252 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2253 sp<FakeWindowHandle> leftWindow =
2254 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2255 leftWindow->setFrame(Rect(0, 0, 200, 200));
2256
2257 sp<FakeWindowHandle> rightWindow =
2258 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2259 rightWindow->setFrame(Rect(200, 0, 400, 200));
2260
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002261 mDispatcher->onWindowInfosChanged(
2262 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002263 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2264 // stale.
2265 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2266 const int32_t mouseDeviceId = 6;
2267 const int32_t touchDeviceId = 4;
2268 // Move the cursor from right
2269 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002270 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002271 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2272 AINPUT_SOURCE_MOUSE)
2273 .deviceId(mouseDeviceId)
2274 .downTime(baseTime + 10)
2275 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002276 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002277 .build()));
2278 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2279
2280 // .. to the left window
2281 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002282 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002283 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2284 AINPUT_SOURCE_MOUSE)
2285 .deviceId(mouseDeviceId)
2286 .downTime(baseTime + 10)
2287 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002288 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002289 .build()));
2290 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2291 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2292 // Now tap the left window
2293 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002294 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002295 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2296 AINPUT_SOURCE_TOUCHSCREEN)
2297 .deviceId(touchDeviceId)
2298 .downTime(baseTime + 40)
2299 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002300 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002301 .build()));
2302 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2303 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2304
2305 // release tap
2306 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002307 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002308 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2309 AINPUT_SOURCE_TOUCHSCREEN)
2310 .deviceId(touchDeviceId)
2311 .downTime(baseTime + 40)
2312 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002313 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002314 .build()));
2315 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2316
2317 // Tap the window on the right
2318 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002319 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002320 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2321 AINPUT_SOURCE_TOUCHSCREEN)
2322 .deviceId(touchDeviceId)
2323 .downTime(baseTime + 60)
2324 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002325 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002326 .build()));
2327 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2328
2329 // release tap
2330 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002331 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002332 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2333 AINPUT_SOURCE_TOUCHSCREEN)
2334 .deviceId(touchDeviceId)
2335 .downTime(baseTime + 60)
2336 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002337 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002338 .build()));
2339 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2340
2341 // No more events
2342 leftWindow->assertNoEvents();
2343 rightWindow->assertNoEvents();
2344}
2345
2346/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002347 * Start hovering in a window. While this hover is still active, make another window appear on top.
2348 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2349 * While the top window is present, the hovering is stopped.
2350 * Later, hovering gets resumed again.
2351 * Ensure that new hover gesture is handled correctly.
2352 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2353 * to the window that's currently being hovered over.
2354 */
2355TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2356 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2357 sp<FakeWindowHandle> window =
2358 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2359 window->setFrame(Rect(0, 0, 200, 200));
2360
2361 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002362 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002363
2364 // Start hovering in the window
2365 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2366 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2367 .build());
2368 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2369
2370 // Now, an obscuring window appears!
2371 sp<FakeWindowHandle> obscuringWindow =
2372 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2373 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002374 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002375 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2376 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2377 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2378 obscuringWindow->setNoInputChannel(true);
2379 obscuringWindow->setFocusable(false);
2380 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002381 mDispatcher->onWindowInfosChanged(
2382 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002383
2384 // While this new obscuring window is present, the hovering is stopped
2385 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2386 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2387 .build());
2388 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2389
2390 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002391 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002392
2393 // And a new hover gesture starts.
2394 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2395 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2396 .build());
2397 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2398}
2399
2400/**
2401 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2402 * the obscuring window.
2403 */
2404TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2405 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2406 sp<FakeWindowHandle> window =
2407 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2408 window->setFrame(Rect(0, 0, 200, 200));
2409
2410 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002411 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002412
2413 // Start hovering in the window
2414 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2415 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2416 .build());
2417 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2418
2419 // Now, an obscuring window appears!
2420 sp<FakeWindowHandle> obscuringWindow =
2421 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2422 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002423 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002424 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2425 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2426 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2427 obscuringWindow->setNoInputChannel(true);
2428 obscuringWindow->setFocusable(false);
2429 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002430 mDispatcher->onWindowInfosChanged(
2431 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002432
2433 // While this new obscuring window is present, the hovering continues. The event can't go to the
2434 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2435 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2436 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2437 .build());
2438 obscuringWindow->assertNoEvents();
2439 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2440
2441 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002442 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002443
2444 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2445 // so it should generate a HOVER_ENTER
2446 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2447 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2448 .build());
2449 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2450
2451 // Now the MOVE should be getting dispatched normally
2452 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2453 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2454 .build());
2455 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2456}
2457
2458/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002459 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2460 * events are delivered to the window.
2461 */
2462TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2463 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2464 sp<FakeWindowHandle> window =
2465 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2466 window->setFrame(Rect(0, 0, 200, 200));
2467 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2468
2469 // Start hovering in the window
2470 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2471 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2472 .build());
2473 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2474
2475 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2476 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2477 .build());
2478 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2479
2480 // Scroll with the mouse
2481 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2482 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2483 .build());
2484 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2485}
2486
2487using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2488
2489/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002490 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2491 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002492 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002493TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002494 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2495 sp<FakeWindowHandle> window =
2496 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2497 window->setFrame(Rect(0, 0, 200, 200));
2498
2499 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2500
2501 constexpr int32_t touchDeviceId = 4;
2502 constexpr int32_t stylusDeviceId = 2;
2503
2504 // Stylus down
2505 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2506 .deviceId(stylusDeviceId)
2507 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2508 .build());
2509 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2510
2511 // Touch down
2512 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2513 .deviceId(touchDeviceId)
2514 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2515 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002516
2517 // Touch move
2518 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2519 .deviceId(touchDeviceId)
2520 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2521 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002522 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002523
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002524 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002525 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2526 .deviceId(stylusDeviceId)
2527 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2528 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002529 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2530 WithCoords(101, 111)));
2531
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002532 window->assertNoEvents();
2533}
2534
2535/**
2536 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002537 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002538 * Similar test as above, but with added SPY window.
2539 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002540TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002541 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2542 sp<FakeWindowHandle> window =
2543 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2544 sp<FakeWindowHandle> spyWindow =
2545 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2546 spyWindow->setFrame(Rect(0, 0, 200, 200));
2547 spyWindow->setTrustedOverlay(true);
2548 spyWindow->setSpy(true);
2549 window->setFrame(Rect(0, 0, 200, 200));
2550
2551 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2552
2553 constexpr int32_t touchDeviceId = 4;
2554 constexpr int32_t stylusDeviceId = 2;
2555
2556 // Stylus down
2557 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2558 .deviceId(stylusDeviceId)
2559 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2560 .build());
2561 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2562 spyWindow->consumeMotionEvent(
2563 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2564
2565 // Touch down
2566 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2567 .deviceId(touchDeviceId)
2568 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2569 .build());
2570
2571 // Touch move
2572 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2573 .deviceId(touchDeviceId)
2574 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2575 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002576
2577 // Touch is ignored because stylus is already down
2578
2579 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002580 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2581 .deviceId(stylusDeviceId)
2582 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2583 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002584 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2585 WithCoords(101, 111)));
2586 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2587 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002588
2589 window->assertNoEvents();
2590 spyWindow->assertNoEvents();
2591}
2592
2593/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002594 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002595 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002596 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002597TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002598 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2599 sp<FakeWindowHandle> window =
2600 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2601 window->setFrame(Rect(0, 0, 200, 200));
2602
2603 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2604
2605 constexpr int32_t touchDeviceId = 4;
2606 constexpr int32_t stylusDeviceId = 2;
2607
2608 // Stylus down on the window
2609 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2610 .deviceId(stylusDeviceId)
2611 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2612 .build());
2613 window->consumeMotionEvent(
2614 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2615
2616 // Touch down on window
2617 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2618 .deviceId(touchDeviceId)
2619 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2620 .build());
2621 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2622 .deviceId(touchDeviceId)
2623 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2624 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002625
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002626 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002627
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002628 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002629 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2630 .deviceId(stylusDeviceId)
2631 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2632 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002633 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2634 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002635
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002636 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002637 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2638 .deviceId(touchDeviceId)
2639 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2640 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002641 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002642}
2643
2644/**
2645 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002646 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002647 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002648TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002649 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2650 sp<FakeWindowHandle> window =
2651 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2652 window->setFrame(Rect(0, 0, 200, 200));
2653
2654 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2655
2656 constexpr int32_t touchDeviceId = 4;
2657 constexpr int32_t stylusDeviceId = 2;
2658
2659 // Touch down on window
2660 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2661 .deviceId(touchDeviceId)
2662 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2663 .build());
2664 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2665 .deviceId(touchDeviceId)
2666 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2667 .build());
2668 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2669 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2670
2671 // Stylus hover on the window
2672 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2673 .deviceId(stylusDeviceId)
2674 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2675 .build());
2676 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2677 .deviceId(stylusDeviceId)
2678 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2679 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002680 // Stylus hover movement causes touch to be canceled
2681 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2682 WithCoords(141, 146)));
2683 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2684 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2685 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2686 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002687
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002688 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002689 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2690 .deviceId(touchDeviceId)
2691 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2692 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002693
2694 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002695}
2696
2697/**
2698 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2699 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2700 * become active.
2701 */
2702TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
2703 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2704 sp<FakeWindowHandle> window =
2705 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2706 window->setFrame(Rect(0, 0, 200, 200));
2707
2708 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2709
2710 constexpr int32_t stylusDeviceId1 = 3;
2711 constexpr int32_t stylusDeviceId2 = 5;
2712
2713 // Touch down on window
2714 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2715 .deviceId(stylusDeviceId1)
2716 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2717 .build());
2718 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2719 .deviceId(stylusDeviceId1)
2720 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2721 .build());
2722 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2723 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2724
2725 // Second stylus down
2726 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2727 .deviceId(stylusDeviceId2)
2728 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2729 .build());
2730 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2731 .deviceId(stylusDeviceId2)
2732 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2733 .build());
2734
2735 // First stylus is canceled, second one takes over.
2736 window->consumeMotionEvent(
2737 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2738 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2739 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2740
2741 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2742 .deviceId(stylusDeviceId1)
2743 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2744 .build());
2745 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002746 window->assertNoEvents();
2747}
2748
2749/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002750 * One window. Touch down on the window. Then, stylus down on the window from another device.
2751 * Ensure that is canceled, because stylus down should be preferred over touch.
2752 */
2753TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
2754 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2755 sp<FakeWindowHandle> window =
2756 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2757 window->setFrame(Rect(0, 0, 200, 200));
2758
2759 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2760
2761 constexpr int32_t touchDeviceId = 4;
2762 constexpr int32_t stylusDeviceId = 2;
2763
2764 // Touch down on window
2765 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2766 .deviceId(touchDeviceId)
2767 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2768 .build());
2769 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2770 .deviceId(touchDeviceId)
2771 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2772 .build());
2773 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2774 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2775
2776 // Stylus down on the window
2777 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2778 .deviceId(stylusDeviceId)
2779 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2780 .build());
2781 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2782 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2783
2784 // Subsequent stylus movements are delivered correctly
2785 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2786 .deviceId(stylusDeviceId)
2787 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2788 .build());
2789 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2790 WithCoords(101, 111)));
2791}
2792
2793/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002794 * Two windows: a window on the left and a window on the right.
2795 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2796 * down. Then, on the left window, also place second touch pointer down.
2797 * This test tries to reproduce a crash.
2798 * In the buggy implementation, second pointer down on the left window would cause a crash.
2799 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002800TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002801 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2802 sp<FakeWindowHandle> leftWindow =
2803 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2804 leftWindow->setFrame(Rect(0, 0, 200, 200));
2805
2806 sp<FakeWindowHandle> rightWindow =
2807 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2808 rightWindow->setFrame(Rect(200, 0, 400, 200));
2809
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002810 mDispatcher->onWindowInfosChanged(
2811 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002812
2813 const int32_t touchDeviceId = 4;
2814 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002815
2816 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002817 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2818 .deviceId(mouseDeviceId)
2819 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2820 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002821 leftWindow->consumeMotionEvent(
2822 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2823
2824 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002825 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2826 .deviceId(mouseDeviceId)
2827 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2828 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2829 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002830
2831 leftWindow->consumeMotionEvent(
2832 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2833 leftWindow->consumeMotionEvent(
2834 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2835
Prabir Pradhan678438e2023-04-13 19:32:51 +00002836 mDispatcher->notifyMotion(
2837 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2838 .deviceId(mouseDeviceId)
2839 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2840 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2841 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2842 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002843 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2844
2845 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002846 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2847 .deviceId(touchDeviceId)
2848 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2849 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002850 leftWindow->assertNoEvents();
2851
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002852 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2853
2854 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002855 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2856 .deviceId(touchDeviceId)
2857 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2858 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2859 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002860 // Since this is now a new splittable pointer going down on the left window, and it's coming
2861 // from a different device, the current gesture in the left window (pointer down) should first
2862 // be canceled.
2863 leftWindow->consumeMotionEvent(
2864 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002865 leftWindow->consumeMotionEvent(
2866 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2867 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2868 // current implementation.
2869 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2870 rightWindow->consumeMotionEvent(
2871 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2872
2873 leftWindow->assertNoEvents();
2874 rightWindow->assertNoEvents();
2875}
2876
2877/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002878 * Two windows: a window on the left and a window on the right.
2879 * Mouse is hovered on the left window and stylus is hovered on the right window.
2880 */
2881TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2882 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2883 sp<FakeWindowHandle> leftWindow =
2884 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2885 leftWindow->setFrame(Rect(0, 0, 200, 200));
2886
2887 sp<FakeWindowHandle> rightWindow =
2888 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2889 rightWindow->setFrame(Rect(200, 0, 400, 200));
2890
2891 mDispatcher->onWindowInfosChanged(
2892 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2893
2894 const int32_t stylusDeviceId = 3;
2895 const int32_t mouseDeviceId = 6;
2896
2897 // Start hovering over the left window
2898 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2899 .deviceId(mouseDeviceId)
2900 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2901 .build());
2902 leftWindow->consumeMotionEvent(
2903 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2904
2905 // Stylus hovered on right window
2906 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2907 .deviceId(stylusDeviceId)
2908 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2909 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002910 rightWindow->consumeMotionEvent(
2911 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2912
2913 // Subsequent HOVER_MOVE events are dispatched correctly.
2914 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2915 .deviceId(mouseDeviceId)
2916 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2917 .build());
2918 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002919 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002920
2921 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2922 .deviceId(stylusDeviceId)
2923 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2924 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002925 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002926 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002927
2928 leftWindow->assertNoEvents();
2929 rightWindow->assertNoEvents();
2930}
2931
2932/**
2933 * Three windows: a window on the left and a window on the right.
2934 * And a spy window that's positioned above all of them.
2935 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2936 * Check the stream that's received by the spy.
2937 */
2938TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2939 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2940
2941 sp<FakeWindowHandle> spyWindow =
2942 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2943 spyWindow->setFrame(Rect(0, 0, 400, 400));
2944 spyWindow->setTrustedOverlay(true);
2945 spyWindow->setSpy(true);
2946
2947 sp<FakeWindowHandle> leftWindow =
2948 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2949 leftWindow->setFrame(Rect(0, 0, 200, 200));
2950
2951 sp<FakeWindowHandle> rightWindow =
2952 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2953
2954 rightWindow->setFrame(Rect(200, 0, 400, 200));
2955
2956 mDispatcher->onWindowInfosChanged(
2957 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2958
2959 const int32_t stylusDeviceId = 1;
2960 const int32_t touchDeviceId = 2;
2961
2962 // Stylus down on the left window
2963 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2964 .deviceId(stylusDeviceId)
2965 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2966 .build());
2967 leftWindow->consumeMotionEvent(
2968 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2969 spyWindow->consumeMotionEvent(
2970 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2971
2972 // Touch down on the right window
2973 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2974 .deviceId(touchDeviceId)
2975 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2976 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002977 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002978 rightWindow->consumeMotionEvent(
2979 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002980
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002981 // Spy window does not receive touch events, because stylus events take precedence, and it
2982 // already has an active stylus gesture.
2983
2984 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002985 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2986 .deviceId(stylusDeviceId)
2987 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2988 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002989 leftWindow->consumeMotionEvent(
2990 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2991 spyWindow->consumeMotionEvent(
2992 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002993
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002994 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002995 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2996 .deviceId(touchDeviceId)
2997 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2998 .build());
2999 rightWindow->consumeMotionEvent(
3000 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003001
3002 spyWindow->assertNoEvents();
3003 leftWindow->assertNoEvents();
3004 rightWindow->assertNoEvents();
3005}
3006
3007/**
3008 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3009 * both.
3010 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003011 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003012 * At the same time, left and right should be getting independent streams of hovering and touch,
3013 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003014 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003015TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003016 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3017
3018 sp<FakeWindowHandle> spyWindow =
3019 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3020 spyWindow->setFrame(Rect(0, 0, 400, 400));
3021 spyWindow->setTrustedOverlay(true);
3022 spyWindow->setSpy(true);
3023
3024 sp<FakeWindowHandle> leftWindow =
3025 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3026 leftWindow->setFrame(Rect(0, 0, 200, 200));
3027
3028 sp<FakeWindowHandle> rightWindow =
3029 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3030 rightWindow->setFrame(Rect(200, 0, 400, 200));
3031
3032 mDispatcher->onWindowInfosChanged(
3033 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3034
3035 const int32_t stylusDeviceId = 1;
3036 const int32_t touchDeviceId = 2;
3037
3038 // Stylus hover on the left window
3039 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3040 .deviceId(stylusDeviceId)
3041 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3042 .build());
3043 leftWindow->consumeMotionEvent(
3044 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3045 spyWindow->consumeMotionEvent(
3046 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3047
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003048 // Touch down on the right window. Spy doesn't receive this touch because it already has
3049 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003050 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3051 .deviceId(touchDeviceId)
3052 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3053 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003054 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003055 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003056 rightWindow->consumeMotionEvent(
3057 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3058
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003059 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003060 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3061 .deviceId(stylusDeviceId)
3062 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3063 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003064 leftWindow->consumeMotionEvent(
3065 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003066 spyWindow->consumeMotionEvent(
3067 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003068
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003069 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003070 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3071 .deviceId(touchDeviceId)
3072 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3073 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003074 rightWindow->consumeMotionEvent(
3075 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3076
3077 spyWindow->assertNoEvents();
3078 leftWindow->assertNoEvents();
3079 rightWindow->assertNoEvents();
3080}
3081
3082/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003083 * On a single window, use two different devices: mouse and touch.
3084 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3085 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3086 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3087 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3088 * represent a new gesture.
3089 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003090TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003091 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3092 sp<FakeWindowHandle> window =
3093 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3094 window->setFrame(Rect(0, 0, 400, 400));
3095
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003096 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003097
3098 const int32_t touchDeviceId = 4;
3099 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003100
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003101 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003102 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3103 .deviceId(touchDeviceId)
3104 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3105 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003106 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003107 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, 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 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003113 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3114 .deviceId(touchDeviceId)
3115 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3116 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3117 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003118 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3119 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3120 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3121
3122 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003123 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3124 .deviceId(mouseDeviceId)
3125 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3126 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3127 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003128
3129 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003130 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003131 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3132
Prabir Pradhan678438e2023-04-13 19:32:51 +00003133 mDispatcher->notifyMotion(
3134 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3135 .deviceId(mouseDeviceId)
3136 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3137 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3138 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3139 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003140 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3141
3142 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003143 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3144 .deviceId(touchDeviceId)
3145 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3146 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3147 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003148 // Since we already canceled this touch gesture, it will be ignored until a completely new
3149 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3150 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3151 // However, mouse movements should continue to work.
3152 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3153 .deviceId(mouseDeviceId)
3154 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3155 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3156 .build());
3157 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3158
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003159 window->assertNoEvents();
3160}
3161
3162/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003163 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3164 * the injected event.
3165 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003166TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003167 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3168 sp<FakeWindowHandle> window =
3169 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3170 window->setFrame(Rect(0, 0, 400, 400));
3171
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003172 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003173
3174 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003175 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3176 // completion.
3177 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003178 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003179 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3180 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003181 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003182 .build()));
3183 window->consumeMotionEvent(
3184 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3185
3186 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3187 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003188 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3189 .deviceId(touchDeviceId)
3190 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3191 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003192
3193 window->consumeMotionEvent(
3194 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3195 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3196}
3197
3198/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003199 * This test is similar to the test above, but the sequence of injected events is different.
3200 *
3201 * Two windows: a window on the left and a window on the right.
3202 * Mouse is hovered over the left window.
3203 * Next, we tap on the left window, where the cursor was last seen.
3204 *
3205 * After that, we inject one finger down onto the right window, and then a second finger down onto
3206 * the left window.
3207 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3208 * window (first), and then another on the left window (second).
3209 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3210 * In the buggy implementation, second finger down on the left window would cause a crash.
3211 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003212TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003213 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3214 sp<FakeWindowHandle> leftWindow =
3215 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3216 leftWindow->setFrame(Rect(0, 0, 200, 200));
3217
3218 sp<FakeWindowHandle> rightWindow =
3219 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3220 rightWindow->setFrame(Rect(200, 0, 400, 200));
3221
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003222 mDispatcher->onWindowInfosChanged(
3223 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003224
3225 const int32_t mouseDeviceId = 6;
3226 const int32_t touchDeviceId = 4;
3227 // Hover over the left window. Keep the cursor there.
3228 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003229 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003230 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3231 AINPUT_SOURCE_MOUSE)
3232 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003233 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003234 .build()));
3235 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3236
3237 // Tap on left window
3238 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003239 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003240 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3241 AINPUT_SOURCE_TOUCHSCREEN)
3242 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003243 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003244 .build()));
3245
3246 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003247 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003248 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3249 AINPUT_SOURCE_TOUCHSCREEN)
3250 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003251 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003252 .build()));
3253 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3254 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3255 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3256
3257 // First finger down on right window
3258 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003259 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003260 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3261 AINPUT_SOURCE_TOUCHSCREEN)
3262 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003263 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003264 .build()));
3265 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3266
3267 // Second finger down on the left window
3268 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003269 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003270 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3271 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003272 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3273 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003274 .build()));
3275 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3276 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3277
3278 // No more events
3279 leftWindow->assertNoEvents();
3280 rightWindow->assertNoEvents();
3281}
3282
3283/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003284 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3285 * While the touch is down, new hover events from the stylus device should be ignored. After the
3286 * touch is gone, stylus hovering should start working again.
3287 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003288TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003289 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3290 sp<FakeWindowHandle> window =
3291 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3292 window->setFrame(Rect(0, 0, 200, 200));
3293
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003294 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003295
3296 const int32_t stylusDeviceId = 5;
3297 const int32_t touchDeviceId = 4;
3298 // Start hovering with stylus
3299 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003300 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003301 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003302 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003303 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003304 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003305 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003306
3307 // Finger down on the window
3308 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003309 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003310 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003311 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003312 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003313 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003314 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003315
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003316 // Continue hovering with stylus.
3317 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003318 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003319 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3320 AINPUT_SOURCE_STYLUS)
3321 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003322 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003323 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003324 // Hovers continue to work
3325 window->consumeMotionEvent(
3326 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003327
3328 // Lift up the finger
3329 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003330 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003331 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3332 AINPUT_SOURCE_TOUCHSCREEN)
3333 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003334 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003335 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003336
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003337 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003338 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003339 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3340 AINPUT_SOURCE_STYLUS)
3341 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003342 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003343 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003344 window->consumeMotionEvent(
3345 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003346 window->assertNoEvents();
3347}
3348
3349/**
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003350 * If stylus is down anywhere on the screen, then touches should not be delivered to windows that
3351 * have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3352 *
3353 * Two windows: one on the left and one on the right.
3354 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3355 * Stylus down on the left window, and then touch down on the right window.
3356 * Check that the right window doesn't get touches while the stylus is down on the left window.
3357 */
3358TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusDownBlocksTouch) {
3359 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3360 sp<FakeWindowHandle> leftWindow =
3361 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3362 ADISPLAY_ID_DEFAULT);
3363 leftWindow->setFrame(Rect(0, 0, 100, 100));
3364
3365 sp<FakeWindowHandle> sbtRightWindow =
3366 sp<FakeWindowHandle>::make(application, mDispatcher,
3367 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3368 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3369 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3370
3371 mDispatcher->onWindowInfosChanged(
3372 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3373
3374 const int32_t stylusDeviceId = 5;
3375 const int32_t touchDeviceId = 4;
3376
3377 // Stylus down in the left window
3378 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3379 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3380 .deviceId(stylusDeviceId)
3381 .build());
3382 leftWindow->consumeMotionEvent(
3383 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3384
3385 // Finger tap on the right window
3386 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3387 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3388 .deviceId(touchDeviceId)
3389 .build());
3390 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3391 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3392 .deviceId(touchDeviceId)
3393 .build());
3394
3395 // The touch should be blocked, because stylus is down somewhere else on screen!
3396 sbtRightWindow->assertNoEvents();
3397
3398 // Continue stylus motion, and ensure it's not impacted.
3399 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3400 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3401 .deviceId(stylusDeviceId)
3402 .build());
3403 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3404 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3405 .deviceId(stylusDeviceId)
3406 .build());
3407 leftWindow->consumeMotionEvent(
3408 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3409 leftWindow->consumeMotionEvent(
3410 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(stylusDeviceId)));
3411
3412 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3413 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3414 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3415 .deviceId(touchDeviceId)
3416 .build());
3417 sbtRightWindow->consumeMotionEvent(
3418 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3419}
3420
3421/**
3422 * If stylus is hovering anywhere on the screen, then touches should not be delivered to windows
3423 * that have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3424 *
3425 * Two windows: one on the left and one on the right.
3426 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3427 * Stylus hover on the left window, and then touch down on the right window.
3428 * Check that the right window doesn't get touches while the stylus is hovering on the left window.
3429 */
3430TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusHoverBlocksTouch) {
3431 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3432 sp<FakeWindowHandle> leftWindow =
3433 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3434 ADISPLAY_ID_DEFAULT);
3435 leftWindow->setFrame(Rect(0, 0, 100, 100));
3436
3437 sp<FakeWindowHandle> sbtRightWindow =
3438 sp<FakeWindowHandle>::make(application, mDispatcher,
3439 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3440 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3441 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3442
3443 mDispatcher->onWindowInfosChanged(
3444 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3445
3446 const int32_t stylusDeviceId = 5;
3447 const int32_t touchDeviceId = 4;
3448
3449 // Stylus hover in the left window
3450 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3451 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3452 .deviceId(stylusDeviceId)
3453 .build());
3454 leftWindow->consumeMotionEvent(
3455 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3456
3457 // Finger tap on the right window
3458 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3459 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3460 .deviceId(touchDeviceId)
3461 .build());
3462 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3463 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3464 .deviceId(touchDeviceId)
3465 .build());
3466
3467 // The touch should be blocked, because stylus is hovering somewhere else on screen!
3468 sbtRightWindow->assertNoEvents();
3469
3470 // Continue stylus motion, and ensure it's not impacted.
3471 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3472 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3473 .deviceId(stylusDeviceId)
3474 .build());
3475 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3476 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3477 .deviceId(stylusDeviceId)
3478 .build());
3479 leftWindow->consumeMotionEvent(
3480 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3481 leftWindow->consumeMotionEvent(
3482 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3483
3484 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3485 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3486 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3487 .deviceId(touchDeviceId)
3488 .build());
3489 sbtRightWindow->consumeMotionEvent(
3490 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3491}
3492
3493/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003494 * A spy window above a window with no input channel.
3495 * Start hovering with a stylus device, and then tap with it.
3496 * Ensure spy window receives the entire sequence.
3497 */
3498TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3499 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3500 sp<FakeWindowHandle> spyWindow =
3501 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3502 spyWindow->setFrame(Rect(0, 0, 200, 200));
3503 spyWindow->setTrustedOverlay(true);
3504 spyWindow->setSpy(true);
3505 sp<FakeWindowHandle> window =
3506 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3507 window->setNoInputChannel(true);
3508 window->setFrame(Rect(0, 0, 200, 200));
3509
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003510 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003511
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003512 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003513 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3514 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3515 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003516 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3517 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003518 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3519 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3520 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003521 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3522
3523 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003524 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3525 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3526 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003527 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3528
3529 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003530 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3531 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3532 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003533 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3534
3535 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003536 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3537 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3538 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003539 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3540 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003541 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3542 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3543 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003544 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3545
3546 // No more events
3547 spyWindow->assertNoEvents();
3548 window->assertNoEvents();
3549}
3550
3551/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003552 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3553 * rejected. But since we already have an ongoing gesture, this event should be processed.
3554 * This prevents inconsistent events being handled inside the dispatcher.
3555 */
3556TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3557 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3558
3559 sp<FakeWindowHandle> window =
3560 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3561 window->setFrame(Rect(0, 0, 200, 200));
3562
3563 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3564
3565 // Start hovering with stylus
3566 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3567 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3568 .build());
3569 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3570
3571 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3572 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3573 .build();
3574 // Make this 'hoverExit' event stale
3575 mFakePolicy->setStaleEventTimeout(100ms);
3576 std::this_thread::sleep_for(100ms);
3577
3578 // It shouldn't be dropped by the dispatcher, even though it's stale.
3579 mDispatcher->notifyMotion(hoverExit);
3580 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3581
3582 // Stylus starts hovering again! There should be no crash.
3583 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3584 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3585 .build());
3586 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3587}
3588
3589/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003590 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3591 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3592 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3593 * While the mouse is down, new move events from the touch device should be ignored.
3594 */
3595TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3596 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3597 sp<FakeWindowHandle> spyWindow =
3598 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3599 spyWindow->setFrame(Rect(0, 0, 200, 200));
3600 spyWindow->setTrustedOverlay(true);
3601 spyWindow->setSpy(true);
3602 sp<FakeWindowHandle> window =
3603 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3604 window->setFrame(Rect(0, 0, 200, 200));
3605
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003606 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003607
3608 const int32_t mouseDeviceId = 7;
3609 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003610
3611 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003612 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3613 .deviceId(mouseDeviceId)
3614 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3615 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003616 spyWindow->consumeMotionEvent(
3617 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3618 window->consumeMotionEvent(
3619 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3620
3621 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003622 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3623 .deviceId(touchDeviceId)
3624 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3625 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003626 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3627 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3628 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3629 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3630
Prabir Pradhan678438e2023-04-13 19:32:51 +00003631 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3632 .deviceId(touchDeviceId)
3633 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3634 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003635 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3636 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3637
3638 // Pilfer the stream
3639 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3640 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3641
Prabir Pradhan678438e2023-04-13 19:32:51 +00003642 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3643 .deviceId(touchDeviceId)
3644 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3645 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003646 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3647
3648 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003649 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3650 .deviceId(mouseDeviceId)
3651 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3652 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3653 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003654
3655 spyWindow->consumeMotionEvent(
3656 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3657 spyWindow->consumeMotionEvent(
3658 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3659 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3660
Prabir Pradhan678438e2023-04-13 19:32:51 +00003661 mDispatcher->notifyMotion(
3662 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3663 .deviceId(mouseDeviceId)
3664 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3665 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3666 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3667 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003668 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3669 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3670
3671 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003672 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3673 .deviceId(mouseDeviceId)
3674 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3675 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3676 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003677 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3678 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3679
3680 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003681 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3682 .deviceId(touchDeviceId)
3683 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3684 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003685
3686 // No more events
3687 spyWindow->assertNoEvents();
3688 window->assertNoEvents();
3689}
3690
3691/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003692 * On the display, have a single window, and also an area where there's no window.
3693 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3694 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3695 */
3696TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3697 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3698 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003699 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003700
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003701 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003702
3703 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003704 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003705
3706 mDispatcher->waitForIdle();
3707 window->assertNoEvents();
3708
3709 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003710 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003711 mDispatcher->waitForIdle();
3712 window->consumeMotionDown();
3713}
3714
3715/**
3716 * Same test as above, but instead of touching the empty space, the first touch goes to
3717 * non-touchable window.
3718 */
3719TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3720 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3721 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003722 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003723 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3724 window1->setTouchable(false);
3725 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003726 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003727 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3728
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003729 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003730
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003731 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003732 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003733
3734 mDispatcher->waitForIdle();
3735 window1->assertNoEvents();
3736 window2->assertNoEvents();
3737
3738 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003739 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003740 mDispatcher->waitForIdle();
3741 window2->consumeMotionDown();
3742}
3743
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003744/**
3745 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3746 * to the event time of the first ACTION_DOWN sent to the particular window.
3747 */
3748TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3749 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3750 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003751 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003752 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3753 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003754 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003755 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3756
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003757 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003758
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003759 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003760 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003761
3762 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003763
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00003764 const MotionEvent& motionEvent1 = window1->consumeMotionEvent();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003765 window2->assertNoEvents();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00003766 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
3767 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003768
3769 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003770 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003771 mDispatcher->waitForIdle();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00003772 const MotionEvent& motionEvent2 = window2->consumeMotionEvent();
3773 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003774 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00003775 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003776
3777 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003778 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003779 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003780 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003781
3782 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003783 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003784 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003785 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003786
3787 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3788 window1->consumeMotionMove();
3789 window1->assertNoEvents();
3790
3791 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003792 mDispatcher->notifyMotion(
3793 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003794 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003795 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003796
Prabir Pradhan678438e2023-04-13 19:32:51 +00003797 mDispatcher->notifyMotion(
3798 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003799 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003800 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003801}
3802
Garfield Tandf26e862020-07-01 20:18:19 -07003803TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003804 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003805 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003806 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003807 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003808 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003809 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003810 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003811
3812 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3813
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003814 mDispatcher->onWindowInfosChanged(
3815 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003816
3817 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003818 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003819 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003820 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3821 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003822 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003823 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003824 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003825
3826 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003827 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003828 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003829 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3830 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003831 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003832 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003833 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3834 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003835
3836 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003837 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003838 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003839 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3840 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003841 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003842 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003843 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3844 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003845
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003846 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003847 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003848 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3849 AINPUT_SOURCE_MOUSE)
3850 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3851 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003852 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003853 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003854 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003855
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003856 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003857 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003858 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3859 AINPUT_SOURCE_MOUSE)
3860 .buttonState(0)
3861 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003862 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003863 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003864 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003865
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003866 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003867 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003868 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3869 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003870 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003871 .build()));
3872 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3873
3874 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003875 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003876 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003877 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3878 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003879 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003880 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003881 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003882
3883 // No more events
3884 windowLeft->assertNoEvents();
3885 windowRight->assertNoEvents();
3886}
3887
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003888/**
3889 * Put two fingers down (and don't release them) and click the mouse button.
3890 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3891 * currently active gesture should be canceled, and the new one should proceed.
3892 */
3893TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3894 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3895 sp<FakeWindowHandle> window =
3896 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3897 window->setFrame(Rect(0, 0, 600, 800));
3898
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003899 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003900
3901 const int32_t touchDeviceId = 4;
3902 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003903
3904 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003905 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3906 .deviceId(touchDeviceId)
3907 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3908 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003909
Prabir Pradhan678438e2023-04-13 19:32:51 +00003910 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3911 .deviceId(touchDeviceId)
3912 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3913 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3914 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003915 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3916 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3917
3918 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003919 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3920 .deviceId(mouseDeviceId)
3921 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3922 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3923 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003924 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3925 WithPointerCount(2u)));
3926 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3927
Prabir Pradhan678438e2023-04-13 19:32:51 +00003928 mDispatcher->notifyMotion(
3929 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3930 .deviceId(mouseDeviceId)
3931 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3932 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3933 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3934 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003935 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3936
3937 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3938 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003939 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3940 .deviceId(touchDeviceId)
3941 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3942 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3943 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003944 window->assertNoEvents();
3945}
3946
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003947TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3948 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3949
3950 sp<FakeWindowHandle> spyWindow =
3951 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3952 spyWindow->setFrame(Rect(0, 0, 600, 800));
3953 spyWindow->setTrustedOverlay(true);
3954 spyWindow->setSpy(true);
3955 sp<FakeWindowHandle> window =
3956 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3957 window->setFrame(Rect(0, 0, 600, 800));
3958
3959 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003960 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003961
3962 // Send mouse cursor to the window
3963 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003964 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003965 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3966 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003967 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003968 .build()));
3969
3970 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3971 WithSource(AINPUT_SOURCE_MOUSE)));
3972 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3973 WithSource(AINPUT_SOURCE_MOUSE)));
3974
3975 window->assertNoEvents();
3976 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003977}
3978
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003979TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3980 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3981
3982 sp<FakeWindowHandle> spyWindow =
3983 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3984 spyWindow->setFrame(Rect(0, 0, 600, 800));
3985 spyWindow->setTrustedOverlay(true);
3986 spyWindow->setSpy(true);
3987 sp<FakeWindowHandle> window =
3988 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3989 window->setFrame(Rect(0, 0, 600, 800));
3990
3991 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003992 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003993
3994 // Send mouse cursor to the window
3995 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003996 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003997 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3998 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003999 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004000 .build()));
4001
4002 // Move mouse cursor
4003 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004004 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004005 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4006 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004007 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004008 .build()));
4009
4010 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4011 WithSource(AINPUT_SOURCE_MOUSE)));
4012 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4013 WithSource(AINPUT_SOURCE_MOUSE)));
4014 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4015 WithSource(AINPUT_SOURCE_MOUSE)));
4016 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4017 WithSource(AINPUT_SOURCE_MOUSE)));
4018 // Touch down on the window
4019 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004020 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004021 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4022 AINPUT_SOURCE_TOUCHSCREEN)
4023 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004024 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004025 .build()));
4026 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4027 WithSource(AINPUT_SOURCE_MOUSE)));
4028 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4029 WithSource(AINPUT_SOURCE_MOUSE)));
4030 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4031 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4032 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4033 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4034
4035 // pilfer the motion, retaining the gesture on the spy window.
4036 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4037 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4038 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4039
4040 // Touch UP on the window
4041 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004042 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004043 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4044 AINPUT_SOURCE_TOUCHSCREEN)
4045 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004046 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004047 .build()));
4048 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4049 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4050
4051 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4052 // to send a new gesture. It should again go to both windows (spy and the window below), just
4053 // like the first gesture did, before pilfering. The window configuration has not changed.
4054
4055 // One more tap - DOWN
4056 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004057 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004058 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4059 AINPUT_SOURCE_TOUCHSCREEN)
4060 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004061 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004062 .build()));
4063 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4064 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4065 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4066 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4067
4068 // Touch UP on the window
4069 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004070 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004071 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4072 AINPUT_SOURCE_TOUCHSCREEN)
4073 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004074 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004075 .build()));
4076 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4077 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4078 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4079 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4080
4081 window->assertNoEvents();
4082 spyWindow->assertNoEvents();
4083}
4084
Garfield Tandf26e862020-07-01 20:18:19 -07004085// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
4086// directly in this test.
4087TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004088 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07004089 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004090 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004091 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004092
4093 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4094
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004095 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004096
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004097 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004098 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004099 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4100 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004101 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004102 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004103 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004104 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004105 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004106 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004107 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4108 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004109 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004110 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004111 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4112 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004113
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004114 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004115 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004116 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4117 AINPUT_SOURCE_MOUSE)
4118 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4119 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004120 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004121 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004122 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004123
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004124 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004125 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004126 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4127 AINPUT_SOURCE_MOUSE)
4128 .buttonState(0)
4129 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004130 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004131 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004132 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004133
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004134 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004135 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004136 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4137 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004138 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004139 .build()));
4140 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
4141
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07004142 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
4143 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
4144 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004145 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004146 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
4147 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004148 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004149 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004150 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004151}
4152
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004153/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004154 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
4155 * is generated.
4156 */
4157TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
4158 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4159 sp<FakeWindowHandle> window =
4160 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4161 window->setFrame(Rect(0, 0, 1200, 800));
4162
4163 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4164
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004165 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004166
4167 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004168 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004169 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4170 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004171 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004172 .build()));
4173 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4174
4175 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004176 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004177 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4178}
4179
4180/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004181 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4182 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004183TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4184 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4185 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004186 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4187 sp<FakeWindowHandle> window =
4188 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4189 window->setFrame(Rect(0, 0, 1200, 800));
4190
4191 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4192
4193 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4194
4195 MotionEventBuilder hoverEnterBuilder =
4196 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4197 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4198 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4199 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4200 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4201 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4202 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4203 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4204 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4205}
4206
4207/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004208 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4209 */
4210TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4211 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4212 sp<FakeWindowHandle> window =
4213 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4214 window->setFrame(Rect(0, 0, 100, 100));
4215
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004216 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004217
4218 const int32_t mouseDeviceId = 7;
4219 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004220
4221 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004222 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4223 .deviceId(mouseDeviceId)
4224 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4225 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004226 window->consumeMotionEvent(
4227 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4228
4229 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004230 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4231 .deviceId(touchDeviceId)
4232 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4233 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004234
4235 window->consumeMotionEvent(
4236 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4237 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4238}
4239
4240/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004241 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004242 * The tap causes a HOVER_EXIT event to be generated because the current event
4243 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004244 */
4245TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4246 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4247 sp<FakeWindowHandle> window =
4248 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4249 window->setFrame(Rect(0, 0, 100, 100));
4250
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004251 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004252 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4253 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4254 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004255 ASSERT_NO_FATAL_FAILURE(
4256 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4257 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004258
4259 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004260 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4261 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4262 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004263 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004264 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4265 WithSource(AINPUT_SOURCE_MOUSE))));
4266
4267 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004268 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4269 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4270
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004271 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4272 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4273 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004274 ASSERT_NO_FATAL_FAILURE(
4275 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4276 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4277}
4278
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004279TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4280 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4281 sp<FakeWindowHandle> windowDefaultDisplay =
4282 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4283 ADISPLAY_ID_DEFAULT);
4284 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4285 sp<FakeWindowHandle> windowSecondDisplay =
4286 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4287 SECOND_DISPLAY_ID);
4288 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4289
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004290 mDispatcher->onWindowInfosChanged(
4291 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004292
4293 // Set cursor position in window in default display and check that hover enter and move
4294 // events are generated.
4295 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004296 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004297 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4298 AINPUT_SOURCE_MOUSE)
4299 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004300 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004301 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004302 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004303
4304 // Remove all windows in secondary display and check that no event happens on window in
4305 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004306 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4307
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004308 windowDefaultDisplay->assertNoEvents();
4309
4310 // Move cursor position in window in default display and check that only hover move
4311 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004312 mDispatcher->onWindowInfosChanged(
4313 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004314 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004315 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004316 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4317 AINPUT_SOURCE_MOUSE)
4318 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004319 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004320 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004321 windowDefaultDisplay->consumeMotionEvent(
4322 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4323 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004324 windowDefaultDisplay->assertNoEvents();
4325}
4326
Garfield Tan00f511d2019-06-12 16:55:40 -07004327TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004328 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004329
4330 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004331 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004332 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004333 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004334 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004335 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004336
4337 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4338
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004339 mDispatcher->onWindowInfosChanged(
4340 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004341
4342 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4343 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004344 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004345 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004346 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004347 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004348 windowRight->assertNoEvents();
4349}
4350
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004351TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004352 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004353 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4354 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004355 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004356
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004357 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004358 setFocusedWindow(window);
4359
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004360 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004361
Prabir Pradhan678438e2023-04-13 19:32:51 +00004362 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004363
4364 // Window should receive key down event.
4365 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4366
4367 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4368 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004369 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004370 window->consumeKeyUp(ADISPLAY_ID_DEFAULT, AKEY_EVENT_FLAG_CANCELED);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004371}
4372
4373TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004374 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004375 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4376 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004377
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004378 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004379
Prabir Pradhan678438e2023-04-13 19:32:51 +00004380 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4381 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004382
4383 // Window should receive motion down event.
4384 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4385
4386 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4387 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004388 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004389 window->consumeMotionEvent(
4390 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004391}
4392
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004393TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4394 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4395 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4396 "Fake Window", ADISPLAY_ID_DEFAULT);
4397
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004398 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004399
4400 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4401 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4402 .build());
4403
4404 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4405
4406 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4407 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4408 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4409
4410 // After the device has been reset, a new hovering stream can be sent to the window
4411 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4412 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4413 .build());
4414 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4415}
4416
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004417TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4418 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004419 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4420 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004421 window->setFocusable(true);
4422
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004423 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004424 setFocusedWindow(window);
4425
4426 window->consumeFocusEvent(true);
4427
Prabir Pradhan678438e2023-04-13 19:32:51 +00004428 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004429 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4430 const nsecs_t injectTime = keyArgs.eventTime;
4431 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004432 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004433 // The dispatching time should be always greater than or equal to intercept key timeout.
4434 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4435 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4436 std::chrono::nanoseconds(interceptKeyTimeout).count());
4437}
4438
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004439/**
4440 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4441 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004442TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4443 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004444 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4445 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004446 window->setFocusable(true);
4447
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004448 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004449 setFocusedWindow(window);
4450
4451 window->consumeFocusEvent(true);
4452
Prabir Pradhan678438e2023-04-13 19:32:51 +00004453 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004454 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004455
4456 // Set a value that's significantly larger than the default consumption timeout. If the
4457 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4458 mFakePolicy->setInterceptKeyTimeout(600ms);
4459 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4460 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004461 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4462}
4463
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004464/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004465 * Two windows. First is a regular window. Second does not overlap with the first, and has
4466 * WATCH_OUTSIDE_TOUCH.
4467 * Both windows are owned by the same UID.
4468 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4469 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4470 */
4471TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4472 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004473 sp<FakeWindowHandle> window =
4474 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004475 window->setFrame(Rect{0, 0, 100, 100});
4476
4477 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004478 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004479 ADISPLAY_ID_DEFAULT);
4480 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4481 outsideWindow->setWatchOutsideTouch(true);
4482 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004483 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004484
4485 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004486 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4487 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4488 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004489 window->consumeMotionDown();
4490 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4491 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4492 outsideWindow->consumeMotionEvent(
4493 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00004494
4495 // Ensure outsideWindow doesn't get any more events for the gesture.
4496 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4497 ADISPLAY_ID_DEFAULT, {PointF{51, 51}}));
4498 window->consumeMotionMove();
4499 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004500}
4501
4502/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004503 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4504 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4505 * ACTION_OUTSIDE event is sent per gesture.
4506 */
4507TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4508 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4509 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004510 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4511 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004512 window->setWatchOutsideTouch(true);
4513 window->setFrame(Rect{0, 0, 100, 100});
4514 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004515 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4516 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004517 secondWindow->setFrame(Rect{100, 100, 200, 200});
4518 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004519 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4520 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004521 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004522 mDispatcher->onWindowInfosChanged(
4523 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004524
4525 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004526 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4527 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4528 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004529 window->assertNoEvents();
4530 secondWindow->assertNoEvents();
4531
4532 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4533 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004534 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4535 ADISPLAY_ID_DEFAULT,
4536 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004537 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4538 window->consumeMotionEvent(
4539 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004540 secondWindow->consumeMotionDown();
4541 thirdWindow->assertNoEvents();
4542
4543 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4544 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004545 mDispatcher->notifyMotion(
4546 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4547 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004548 window->assertNoEvents();
4549 secondWindow->consumeMotionMove();
4550 thirdWindow->consumeMotionDown();
4551}
4552
Prabir Pradhan814fe082022-07-22 20:22:18 +00004553TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4554 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004555 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4556 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004557 window->setFocusable(true);
4558
Patrick Williamsd828f302023-04-28 17:52:08 -05004559 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004560 setFocusedWindow(window);
4561
4562 window->consumeFocusEvent(true);
4563
Prabir Pradhan678438e2023-04-13 19:32:51 +00004564 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4565 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4566 mDispatcher->notifyKey(keyDown);
4567 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004568
4569 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4570 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4571
4572 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004573 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004574
4575 window->consumeFocusEvent(false);
4576
Prabir Pradhan678438e2023-04-13 19:32:51 +00004577 mDispatcher->notifyKey(keyDown);
4578 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004579 window->assertNoEvents();
4580}
4581
Arthur Hung96483742022-11-15 03:30:48 +00004582TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4583 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4584 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4585 "Fake Window", ADISPLAY_ID_DEFAULT);
4586 // Ensure window is non-split and have some transform.
4587 window->setPreventSplitting(true);
4588 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004589 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004590
4591 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004592 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004593 {50, 50}))
4594 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4595 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4596
4597 const MotionEvent secondFingerDownEvent =
4598 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4599 .displayId(ADISPLAY_ID_DEFAULT)
4600 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004601 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4602 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004603 .build();
4604 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004605 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004606 InputEventInjectionSync::WAIT_FOR_RESULT))
4607 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4608
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004609 const MotionEvent& event = window->consumeMotionEvent();
4610 EXPECT_EQ(POINTER_1_DOWN, event.getAction());
4611 EXPECT_EQ(70, event.getX(0)); // 50 + 20
4612 EXPECT_EQ(90, event.getY(0)); // 50 + 40
4613 EXPECT_EQ(-10, event.getX(1)); // -30 + 20
4614 EXPECT_EQ(-10, event.getY(1)); // -50 + 40
Arthur Hung96483742022-11-15 03:30:48 +00004615}
4616
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004617/**
4618 * Two windows: a splittable and a non-splittable.
4619 * The non-splittable window shouldn't receive any "incomplete" gestures.
4620 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4621 * The second pointer should be dropped because the initial window is splittable, so it won't get
4622 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4623 * "incomplete" gestures.
4624 */
4625TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4626 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4627 sp<FakeWindowHandle> leftWindow =
4628 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4629 ADISPLAY_ID_DEFAULT);
4630 leftWindow->setPreventSplitting(false);
4631 leftWindow->setFrame(Rect(0, 0, 100, 100));
4632 sp<FakeWindowHandle> rightWindow =
4633 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4634 ADISPLAY_ID_DEFAULT);
4635 rightWindow->setPreventSplitting(true);
4636 rightWindow->setFrame(Rect(100, 100, 200, 200));
4637 mDispatcher->onWindowInfosChanged(
4638 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4639
4640 // Touch down on left, splittable window
4641 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4642 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4643 .build());
4644 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4645
4646 mDispatcher->notifyMotion(
4647 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4648 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4649 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4650 .build());
4651 leftWindow->assertNoEvents();
4652 rightWindow->assertNoEvents();
4653}
4654
Harry Cuttsb166c002023-05-09 13:06:05 +00004655TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4656 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4657 sp<FakeWindowHandle> window =
4658 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4659 window->setFrame(Rect(0, 0, 400, 400));
4660 sp<FakeWindowHandle> trustedOverlay =
4661 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4662 ADISPLAY_ID_DEFAULT);
4663 trustedOverlay->setSpy(true);
4664 trustedOverlay->setTrustedOverlay(true);
4665
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004666 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004667
4668 // Start a three-finger touchpad swipe
4669 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4670 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4671 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4672 .build());
4673 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4674 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4675 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4676 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4677 .build());
4678 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4679 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4680 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4681 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4682 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4683 .build());
4684
4685 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4686 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4687 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4688
4689 // Move the swipe a bit
4690 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4691 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4692 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4693 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4694 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4695 .build());
4696
4697 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4698
4699 // End the swipe
4700 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4701 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4702 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4703 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4704 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4705 .build());
4706 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4707 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4708 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4709 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4710 .build());
4711 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4712 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4713 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4714 .build());
4715
4716 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4717 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4718 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4719
4720 window->assertNoEvents();
4721}
4722
4723TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4724 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4725 sp<FakeWindowHandle> window =
4726 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4727 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004728 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004729
4730 // Start a three-finger touchpad swipe
4731 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4732 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4733 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4734 .build());
4735 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4736 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4737 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4738 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4739 .build());
4740 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4741 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4742 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4743 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4744 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4745 .build());
4746
4747 // Move the swipe a bit
4748 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4749 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4750 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4751 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4752 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4753 .build());
4754
4755 // End the swipe
4756 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4757 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4758 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4759 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4760 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4761 .build());
4762 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4763 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4764 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4765 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4766 .build());
4767 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4768 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4769 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4770 .build());
4771
4772 window->assertNoEvents();
4773}
4774
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004775/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004776 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4777 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004778 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004779 */
4780TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4781 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4782 sp<FakeWindowHandle> window =
4783 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4784 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004785 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004786
4787 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4788 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4789 .downTime(baseTime + 10)
4790 .eventTime(baseTime + 10)
4791 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4792 .build());
4793
4794 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4795
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004796 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004797 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004798
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004799 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004800
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004801 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4802 .downTime(baseTime + 10)
4803 .eventTime(baseTime + 30)
4804 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4805 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4806 .build());
4807
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004808 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4809
4810 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004811 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4812 .downTime(baseTime + 10)
4813 .eventTime(baseTime + 40)
4814 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4815 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4816 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004817
4818 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4819
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004820 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4821 .downTime(baseTime + 10)
4822 .eventTime(baseTime + 50)
4823 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4824 .build());
4825
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004826 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4827
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004828 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4829 .downTime(baseTime + 60)
4830 .eventTime(baseTime + 60)
4831 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4832 .build());
4833
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004834 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004835}
4836
4837/**
Hu Guo771a7692023-09-17 20:51:08 +08004838 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4839 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4840 * its coordinates should be converted by the transform of the windows of target screen.
4841 */
4842TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4843 // This case will create a window and a spy window on the default display and mirror
4844 // window on the second display. cancel event is sent through spy window pilferPointers
4845 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4846
4847 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4848 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4849 spyWindowDefaultDisplay->setTrustedOverlay(true);
4850 spyWindowDefaultDisplay->setSpy(true);
4851
4852 sp<FakeWindowHandle> windowDefaultDisplay =
4853 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4854 ADISPLAY_ID_DEFAULT);
4855 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4856
4857 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4858 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4859
4860 // Add the windows to the dispatcher
4861 mDispatcher->onWindowInfosChanged(
4862 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4863 *windowSecondDisplay->getInfo()},
4864 {},
4865 0,
4866 0});
4867
4868 // Send down to ADISPLAY_ID_DEFAULT
4869 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4870 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4871 {100, 100}))
4872 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4873
4874 spyWindowDefaultDisplay->consumeMotionDown();
4875 windowDefaultDisplay->consumeMotionDown();
4876
4877 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4878
4879 // windowDefaultDisplay gets cancel
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004880 const MotionEvent& event = windowDefaultDisplay->consumeMotionEvent();
4881 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event.getAction());
Hu Guo771a7692023-09-17 20:51:08 +08004882
4883 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4884 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4885 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4886 // SECOND_DISPLAY_ID, the x and y coordinates are 200
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004887 EXPECT_EQ(100, event.getX(0));
4888 EXPECT_EQ(100, event.getY(0));
Hu Guo771a7692023-09-17 20:51:08 +08004889}
4890
4891/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004892 * Ensure the correct coordinate spaces are used by InputDispatcher.
4893 *
4894 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4895 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4896 * space.
4897 */
4898class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4899public:
4900 void SetUp() override {
4901 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004902 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004903 }
4904
4905 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4906 gui::DisplayInfo info;
4907 info.displayId = displayId;
4908 info.transform = transform;
4909 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004910 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004911 }
4912
4913 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4914 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004915 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004916 }
4917
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004918 void removeAllWindowsAndDisplays() {
4919 mDisplayInfos.clear();
4920 mWindowInfos.clear();
4921 }
4922
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004923 // Set up a test scenario where the display has a scaled projection and there are two windows
4924 // on the display.
4925 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4926 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4927 // respectively.
4928 ui::Transform displayTransform;
4929 displayTransform.set(2, 0, 0, 4);
4930 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4931
4932 std::shared_ptr<FakeApplicationHandle> application =
4933 std::make_shared<FakeApplicationHandle>();
4934
4935 // Add two windows to the display. Their frames are represented in the display space.
4936 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004937 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4938 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004939 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4940 addWindow(firstWindow);
4941
4942 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004943 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4944 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004945 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4946 addWindow(secondWindow);
4947 return {std::move(firstWindow), std::move(secondWindow)};
4948 }
4949
4950private:
4951 std::vector<gui::DisplayInfo> mDisplayInfos;
4952 std::vector<gui::WindowInfo> mWindowInfos;
4953};
4954
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004955TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004956 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4957 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004958 // selected so that if the hit test was performed with the point and the bounds being in
4959 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004960 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4961 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4962 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004963
4964 firstWindow->consumeMotionDown();
4965 secondWindow->assertNoEvents();
4966}
4967
4968// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4969// the event should be treated as being in the logical display space.
4970TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4971 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4972 // Send down to the first window. The point is represented in the logical display space. The
4973 // point is selected so that if the hit test was done in logical display space, then it would
4974 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004975 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004976 PointF{75 * 2, 55 * 4});
4977
4978 firstWindow->consumeMotionDown();
4979 secondWindow->assertNoEvents();
4980}
4981
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004982// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4983// event should be treated as being in the logical display space.
4984TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4985 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4986
4987 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4988 ui::Transform injectedEventTransform;
4989 injectedEventTransform.set(matrix);
4990 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4991 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4992
4993 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4994 .displayId(ADISPLAY_ID_DEFAULT)
4995 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004996 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004997 .x(untransformedPoint.x)
4998 .y(untransformedPoint.y))
4999 .build();
5000 event.transform(matrix);
5001
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005002 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005003 InputEventInjectionSync::WAIT_FOR_RESULT);
5004
5005 firstWindow->consumeMotionDown();
5006 secondWindow->assertNoEvents();
5007}
5008
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005009TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
5010 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5011
5012 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005013 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5014 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5015 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005016
5017 firstWindow->assertNoEvents();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00005018 const MotionEvent& event = secondWindow->consumeMotionEvent();
5019 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event.getAction());
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005020
5021 // Ensure that the events from the "getRaw" API are in logical display coordinates.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00005022 EXPECT_EQ(300, event.getRawX(0));
5023 EXPECT_EQ(880, event.getRawY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005024
5025 // Ensure that the x and y values are in the window's coordinate space.
5026 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
5027 // the logical display space. This will be the origin of the window space.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00005028 EXPECT_EQ(100, event.getX(0));
5029 EXPECT_EQ(80, event.getY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005030}
5031
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005032TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
5033 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5034 // The monitor will always receive events in the logical display's coordinate space, because
5035 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00005036 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005037
5038 // Send down to the first window.
5039 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5040 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5041 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5042 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5043
5044 // Second pointer goes down on second window.
5045 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5046 ADISPLAY_ID_DEFAULT,
5047 {PointF{50, 100}, PointF{150, 220}}));
5048 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
5049 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
5050 {1, PointF{300, 880}}};
5051 monitor.consumeMotionEvent(
5052 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
5053
5054 mDispatcher->cancelCurrentTouch();
5055
5056 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5057 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
5058 monitor.consumeMotionEvent(
5059 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
5060}
5061
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005062TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
5063 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5064
5065 // Send down to the first window.
5066 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5067 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5068 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5069
5070 // The pointer is transferred to the second window, and the second window receives it in the
5071 // correct coordinate space.
5072 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5073 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5074 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
5075}
5076
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005077TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
5078 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5079
5080 // Send hover move to the second window, and ensure it shows up as hover enter.
5081 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5082 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5083 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5084 WithCoords(100, 80), WithRawCoords(300, 880)));
5085
5086 // Touch down at the same location and ensure a hover exit is synthesized.
5087 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5088 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5089 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5090 WithRawCoords(300, 880)));
5091 secondWindow->consumeMotionEvent(
5092 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5093 secondWindow->assertNoEvents();
5094 firstWindow->assertNoEvents();
5095}
5096
Prabir Pradhan453ae732023-10-13 14:30:14 +00005097// Same as above, but while the window is being mirrored.
5098TEST_F(InputDispatcherDisplayProjectionTest,
5099 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
5100 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5101
5102 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5103 ui::Transform secondDisplayTransform;
5104 secondDisplayTransform.set(matrix);
5105 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5106
5107 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5108 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5109 addWindow(secondWindowClone);
5110
5111 // Send hover move to the second window, and ensure it shows up as hover enter.
5112 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5113 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5114 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5115 WithCoords(100, 80), WithRawCoords(300, 880)));
5116
5117 // Touch down at the same location and ensure a hover exit is synthesized for the correct
5118 // display.
5119 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5120 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5121 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5122 WithRawCoords(300, 880)));
5123 secondWindow->consumeMotionEvent(
5124 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5125 secondWindow->assertNoEvents();
5126 firstWindow->assertNoEvents();
5127}
5128
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005129TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
5130 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5131
5132 // Send hover enter to second window
5133 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5134 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5135 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5136 WithCoords(100, 80), WithRawCoords(300, 880)));
5137
5138 mDispatcher->cancelCurrentTouch();
5139
5140 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5141 WithRawCoords(300, 880)));
5142 secondWindow->assertNoEvents();
5143 firstWindow->assertNoEvents();
5144}
5145
Prabir Pradhan453ae732023-10-13 14:30:14 +00005146// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00005147TEST_F(InputDispatcherDisplayProjectionTest,
5148 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
5149 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5150
5151 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5152 ui::Transform secondDisplayTransform;
5153 secondDisplayTransform.set(matrix);
5154 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5155
5156 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5157 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5158 addWindow(secondWindowClone);
5159
5160 // Send hover enter to second window
5161 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5162 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5163 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5164 WithCoords(100, 80), WithRawCoords(300, 880),
5165 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5166
5167 mDispatcher->cancelCurrentTouch();
5168
5169 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
5170 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5171 WithRawCoords(300, 880),
5172 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5173 secondWindow->assertNoEvents();
5174 firstWindow->assertNoEvents();
5175}
5176
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005177/** Ensure consistent behavior of InputDispatcher in all orientations. */
5178class InputDispatcherDisplayOrientationFixture
5179 : public InputDispatcherDisplayProjectionTest,
5180 public ::testing::WithParamInterface<ui::Rotation> {};
5181
5182// This test verifies the touchable region of a window for all rotations of the display by tapping
5183// in different locations on the display, specifically points close to the four corners of a
5184// window.
5185TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
5186 constexpr static int32_t displayWidth = 400;
5187 constexpr static int32_t displayHeight = 800;
5188
5189 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5190
5191 const auto rotation = GetParam();
5192
5193 // Set up the display with the specified rotation.
5194 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5195 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5196 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5197 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5198 logicalDisplayWidth, logicalDisplayHeight);
5199 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5200
5201 // Create a window with its bounds determined in the logical display.
5202 const Rect frameInLogicalDisplay(100, 100, 200, 300);
5203 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
5204 sp<FakeWindowHandle> window =
5205 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5206 window->setFrame(frameInDisplay, displayTransform);
5207 addWindow(window);
5208
5209 // The following points in logical display space should be inside the window.
5210 static const std::array<vec2, 4> insidePoints{
5211 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5212 for (const auto pointInsideWindow : insidePoints) {
5213 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
5214 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005215 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5216 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5217 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005218 window->consumeMotionDown();
5219
Prabir Pradhan678438e2023-04-13 19:32:51 +00005220 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5221 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5222 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005223 window->consumeMotionUp();
5224 }
5225
5226 // The following points in logical display space should be outside the window.
5227 static const std::array<vec2, 5> outsidePoints{
5228 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
5229 for (const auto pointOutsideWindow : outsidePoints) {
5230 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
5231 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005232 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5233 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5234 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005235
Prabir Pradhan678438e2023-04-13 19:32:51 +00005236 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5237 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5238 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005239 }
5240 window->assertNoEvents();
5241}
5242
5243// Run the precision tests for all rotations.
5244INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
5245 InputDispatcherDisplayOrientationFixture,
5246 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
5247 ui::ROTATION_270),
5248 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
5249 return ftl::enum_string(testParamInfo.param);
5250 });
5251
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005252using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
5253 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005254
5255class TransferTouchFixture : public InputDispatcherTest,
5256 public ::testing::WithParamInterface<TransferFunction> {};
5257
5258TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07005259 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005260
5261 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005262 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005263 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5264 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005265 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005266 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005267 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5268 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005269 sp<FakeWindowHandle> wallpaper =
5270 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
5271 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005272 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005273 mDispatcher->onWindowInfosChanged(
5274 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005275
5276 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005277 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5278 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005279
Svet Ganov5d3bc372020-01-26 23:11:07 -08005280 // Only the first window should get the down event
5281 firstWindow->consumeMotionDown();
5282 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005283 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005284
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005285 // Transfer touch to the second window
5286 TransferFunction f = GetParam();
5287 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5288 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005289 // The first window gets cancel and the second gets down
5290 firstWindow->consumeMotionCancel();
5291 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005292 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005293
5294 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005295 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5296 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005297 // The first window gets no events and the second gets up
5298 firstWindow->assertNoEvents();
5299 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005300 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005301}
5302
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005303/**
5304 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
5305 * from. When we have spy windows, there are several windows to choose from: either spy, or the
5306 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
5307 * natural to the user.
5308 * In this test, we are sending a pointer to both spy window and first window. We then try to
5309 * transfer touch to the second window. The dispatcher should identify the first window as the
5310 * one that should lose the gesture, and therefore the action should be to move the gesture from
5311 * the first window to the second.
5312 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
5313 * the other API, as well.
5314 */
5315TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5316 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5317
5318 // Create a couple of windows + a spy window
5319 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005320 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005321 spyWindow->setTrustedOverlay(true);
5322 spyWindow->setSpy(true);
5323 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005324 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005325 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005326 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005327
5328 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005329 mDispatcher->onWindowInfosChanged(
5330 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005331
5332 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005333 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5334 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005335 // Only the first window and spy should get the down event
5336 spyWindow->consumeMotionDown();
5337 firstWindow->consumeMotionDown();
5338
5339 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
5340 // if f === 'transferTouch'.
5341 TransferFunction f = GetParam();
5342 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5343 ASSERT_TRUE(success);
5344 // The first window gets cancel and the second gets down
5345 firstWindow->consumeMotionCancel();
5346 secondWindow->consumeMotionDown();
5347
5348 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005349 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5350 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005351 // The first window gets no events and the second+spy get up
5352 firstWindow->assertNoEvents();
5353 spyWindow->consumeMotionUp();
5354 secondWindow->consumeMotionUp();
5355}
5356
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005357TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005358 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005359
5360 PointF touchPoint = {10, 10};
5361
5362 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005363 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005364 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5365 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005366 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005367 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005368 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5369 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005370 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005371
5372 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005373 mDispatcher->onWindowInfosChanged(
5374 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005375
5376 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005377 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5378 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5379 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005380 // Only the first window should get the down event
5381 firstWindow->consumeMotionDown();
5382 secondWindow->assertNoEvents();
5383
5384 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005385 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5386 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005387 // Only the first window should get the pointer down event
5388 firstWindow->consumeMotionPointerDown(1);
5389 secondWindow->assertNoEvents();
5390
5391 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005392 TransferFunction f = GetParam();
5393 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5394 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005395 // The first window gets cancel and the second gets down and pointer down
5396 firstWindow->consumeMotionCancel();
5397 secondWindow->consumeMotionDown();
5398 secondWindow->consumeMotionPointerDown(1);
5399
5400 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005401 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5402 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005403 // The first window gets nothing and the second gets pointer up
5404 firstWindow->assertNoEvents();
5405 secondWindow->consumeMotionPointerUp(1);
5406
5407 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005408 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5409 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005410 // The first window gets nothing and the second gets up
5411 firstWindow->assertNoEvents();
5412 secondWindow->consumeMotionUp();
5413}
5414
Arthur Hungc539dbb2022-12-08 07:45:36 +00005415TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5416 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5417
5418 // Create a couple of windows
5419 sp<FakeWindowHandle> firstWindow =
5420 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5421 ADISPLAY_ID_DEFAULT);
5422 firstWindow->setDupTouchToWallpaper(true);
5423 sp<FakeWindowHandle> secondWindow =
5424 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5425 ADISPLAY_ID_DEFAULT);
5426 secondWindow->setDupTouchToWallpaper(true);
5427
5428 sp<FakeWindowHandle> wallpaper1 =
5429 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5430 wallpaper1->setIsWallpaper(true);
5431
5432 sp<FakeWindowHandle> wallpaper2 =
5433 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5434 wallpaper2->setIsWallpaper(true);
5435 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005436 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5437 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5438 {},
5439 0,
5440 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005441
5442 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005443 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5444 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005445
5446 // Only the first window should get the down event
5447 firstWindow->consumeMotionDown();
5448 secondWindow->assertNoEvents();
5449 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5450 wallpaper2->assertNoEvents();
5451
5452 // Transfer touch focus to the second window
5453 TransferFunction f = GetParam();
5454 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5455 ASSERT_TRUE(success);
5456
5457 // The first window gets cancel and the second gets down
5458 firstWindow->consumeMotionCancel();
5459 secondWindow->consumeMotionDown();
5460 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5461 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5462
5463 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005464 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5465 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005466 // The first window gets no events and the second gets up
5467 firstWindow->assertNoEvents();
5468 secondWindow->consumeMotionUp();
5469 wallpaper1->assertNoEvents();
5470 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5471}
5472
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005473// For the cases of single pointer touch and two pointers non-split touch, the api's
5474// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5475// for the case where there are multiple pointers split across several windows.
5476INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5477 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005478 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5479 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005480 return dispatcher->transferTouch(destChannelToken,
5481 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005482 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005483 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5484 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005485 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005486 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005487 }));
5488
Svet Ganov5d3bc372020-01-26 23:11:07 -08005489TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005490 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005491
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005492 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005493 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5494 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005495 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005496
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005497 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005498 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5499 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005500 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005501
5502 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005503 mDispatcher->onWindowInfosChanged(
5504 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005505
5506 PointF pointInFirst = {300, 200};
5507 PointF pointInSecond = {300, 600};
5508
5509 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005510 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5511 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5512 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005513 // Only the first window should get the down event
5514 firstWindow->consumeMotionDown();
5515 secondWindow->assertNoEvents();
5516
5517 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005518 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5519 ADISPLAY_ID_DEFAULT,
5520 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005521 // The first window gets a move and the second a down
5522 firstWindow->consumeMotionMove();
5523 secondWindow->consumeMotionDown();
5524
5525 // Transfer touch focus to the second window
5526 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5527 // The first window gets cancel and the new gets pointer down (it already saw down)
5528 firstWindow->consumeMotionCancel();
5529 secondWindow->consumeMotionPointerDown(1);
5530
5531 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005532 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5533 ADISPLAY_ID_DEFAULT,
5534 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005535 // The first window gets nothing and the second gets pointer up
5536 firstWindow->assertNoEvents();
5537 secondWindow->consumeMotionPointerUp(1);
5538
5539 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005540 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5541 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005542 // The first window gets nothing and the second gets up
5543 firstWindow->assertNoEvents();
5544 secondWindow->consumeMotionUp();
5545}
5546
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005547// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5548// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5549// touch is not supported, so the touch should continue on those windows and the transferred-to
5550// window should get nothing.
5551TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5552 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5553
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005554 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005555 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5556 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005557 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005558
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005559 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005560 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5561 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005562 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005563
5564 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005565 mDispatcher->onWindowInfosChanged(
5566 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005567
5568 PointF pointInFirst = {300, 200};
5569 PointF pointInSecond = {300, 600};
5570
5571 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005572 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5573 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5574 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005575 // Only the first window should get the down event
5576 firstWindow->consumeMotionDown();
5577 secondWindow->assertNoEvents();
5578
5579 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005580 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5581 ADISPLAY_ID_DEFAULT,
5582 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005583 // The first window gets a move and the second a down
5584 firstWindow->consumeMotionMove();
5585 secondWindow->consumeMotionDown();
5586
5587 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005588 const bool transferred =
5589 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005590 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5591 ASSERT_FALSE(transferred);
5592 firstWindow->assertNoEvents();
5593 secondWindow->assertNoEvents();
5594
5595 // The rest of the dispatch should proceed as normal
5596 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005597 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5598 ADISPLAY_ID_DEFAULT,
5599 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005600 // The first window gets MOVE and the second gets pointer up
5601 firstWindow->consumeMotionMove();
5602 secondWindow->consumeMotionUp();
5603
5604 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005605 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5606 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005607 // The first window gets nothing and the second gets up
5608 firstWindow->consumeMotionUp();
5609 secondWindow->assertNoEvents();
5610}
5611
Arthur Hungabbb9d82021-09-01 14:52:30 +00005612// This case will create two windows and one mirrored window on the default display and mirror
5613// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5614// the windows info of second display before default display.
5615TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5616 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5617 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005618 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005619 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005620 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005621 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005622 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005623
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005624 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005625 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005626
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005627 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005628 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005629
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005630 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005631 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005632
5633 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005634 mDispatcher->onWindowInfosChanged(
5635 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5636 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5637 *secondWindowInPrimary->getInfo()},
5638 {},
5639 0,
5640 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005641
5642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005643 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005644 {50, 50}))
5645 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5646
5647 // Window should receive motion event.
5648 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5649
5650 // Transfer touch focus
5651 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5652 secondWindowInPrimary->getToken()));
5653 // The first window gets cancel.
5654 firstWindowInPrimary->consumeMotionCancel();
5655 secondWindowInPrimary->consumeMotionDown();
5656
5657 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005658 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005659 ADISPLAY_ID_DEFAULT, {150, 50}))
5660 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5661 firstWindowInPrimary->assertNoEvents();
5662 secondWindowInPrimary->consumeMotionMove();
5663
5664 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005665 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005666 {150, 50}))
5667 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5668 firstWindowInPrimary->assertNoEvents();
5669 secondWindowInPrimary->consumeMotionUp();
5670}
5671
5672// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5673// 'transferTouch' api.
5674TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5675 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5676 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005677 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005678 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005679 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005680 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005681 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005682
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005683 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005684 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005685
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005686 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005687 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005688
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005689 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005690 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005691
5692 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005693 mDispatcher->onWindowInfosChanged(
5694 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5695 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5696 *secondWindowInPrimary->getInfo()},
5697 {},
5698 0,
5699 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005700
5701 // Touch on second display.
5702 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005703 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5704 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005705 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5706
5707 // Window should receive motion event.
5708 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5709
5710 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005711 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005712
5713 // The first window gets cancel.
5714 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5715 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5716
5717 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005718 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005719 SECOND_DISPLAY_ID, {150, 50}))
5720 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5721 firstWindowInPrimary->assertNoEvents();
5722 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5723
5724 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005725 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005726 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5727 firstWindowInPrimary->assertNoEvents();
5728 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5729}
5730
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005731TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005732 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005733 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5734 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005735
Vishnu Nair47074b82020-08-14 11:54:47 -07005736 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005737 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005738 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005739
5740 window->consumeFocusEvent(true);
5741
Prabir Pradhan678438e2023-04-13 19:32:51 +00005742 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005743
5744 // Window should receive key down event.
5745 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005746
5747 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005748 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005749 mFakePolicy->assertUserActivityPoked();
5750}
5751
5752TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5753 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5754 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5755 "Fake Window", ADISPLAY_ID_DEFAULT);
5756
5757 window->setDisableUserActivity(true);
5758 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005759 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005760 setFocusedWindow(window);
5761
5762 window->consumeFocusEvent(true);
5763
5764 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5765
5766 // Window should receive key down event.
5767 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5768
5769 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005770 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005771 mFakePolicy->assertUserActivityNotPoked();
5772}
5773
5774TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5775 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5776 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5777 "Fake Window", ADISPLAY_ID_DEFAULT);
5778
5779 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005780 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005781 setFocusedWindow(window);
5782
5783 window->consumeFocusEvent(true);
5784
5785 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5786 mDispatcher->waitForIdle();
5787
5788 // System key is not passed down
5789 window->assertNoEvents();
5790
5791 // Should have poked user activity
5792 mFakePolicy->assertUserActivityPoked();
5793}
5794
5795TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5796 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5797 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5798 "Fake Window", ADISPLAY_ID_DEFAULT);
5799
5800 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005801 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005802 setFocusedWindow(window);
5803
5804 window->consumeFocusEvent(true);
5805
5806 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5807 mDispatcher->waitForIdle();
5808
5809 // System key is not passed down
5810 window->assertNoEvents();
5811
5812 // Should have poked user activity
5813 mFakePolicy->assertUserActivityPoked();
5814}
5815
5816TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5817 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5818 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5819 "Fake Window", ADISPLAY_ID_DEFAULT);
5820
5821 window->setDisableUserActivity(true);
5822 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005823 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005824 setFocusedWindow(window);
5825
5826 window->consumeFocusEvent(true);
5827
5828 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5829 mDispatcher->waitForIdle();
5830
5831 // System key is not passed down
5832 window->assertNoEvents();
5833
5834 // Should have poked user activity
5835 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005836}
5837
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005838TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5839 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5840 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5841 "Fake Window", ADISPLAY_ID_DEFAULT);
5842
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005843 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005844
5845 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005846 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005847 ADISPLAY_ID_DEFAULT, {100, 100}))
5848 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5849
5850 window->consumeMotionEvent(
5851 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5852
5853 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005854 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005855 mFakePolicy->assertUserActivityPoked();
5856}
5857
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005858TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005859 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005860 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5861 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005862
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005863 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005864
Prabir Pradhan678438e2023-04-13 19:32:51 +00005865 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005866 mDispatcher->waitForIdle();
5867
5868 window->assertNoEvents();
5869}
5870
5871// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5872TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005873 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005874 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5875 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005876
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005877 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005878
5879 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005880 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005881 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005882 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5883 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005884
5885 // Window should receive only the motion event
5886 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5887 window->assertNoEvents(); // Key event or focus event will not be received
5888}
5889
arthurhungea3f4fc2020-12-21 23:18:53 +08005890TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5891 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5892
arthurhungea3f4fc2020-12-21 23:18:53 +08005893 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005894 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5895 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005896 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005897
arthurhungea3f4fc2020-12-21 23:18:53 +08005898 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005899 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5900 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005901 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005902
5903 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005904 mDispatcher->onWindowInfosChanged(
5905 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005906
5907 PointF pointInFirst = {300, 200};
5908 PointF pointInSecond = {300, 600};
5909
5910 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005911 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5912 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5913 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005914 // Only the first window should get the down event
5915 firstWindow->consumeMotionDown();
5916 secondWindow->assertNoEvents();
5917
5918 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005919 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5920 ADISPLAY_ID_DEFAULT,
5921 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005922 // The first window gets a move and the second a down
5923 firstWindow->consumeMotionMove();
5924 secondWindow->consumeMotionDown();
5925
5926 // Send pointer cancel to the second window
5927 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005928 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005929 {pointInFirst, pointInSecond});
5930 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005931 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005932 // The first window gets move and the second gets cancel.
5933 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5934 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5935
5936 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005937 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5938 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005939 // The first window gets up and the second gets nothing.
5940 firstWindow->consumeMotionUp();
5941 secondWindow->assertNoEvents();
5942}
5943
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005944TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5945 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5946
5947 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005948 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005949 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005950 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5951 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5952 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5953
Harry Cutts33476232023-01-30 19:57:29 +00005954 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005955 window->assertNoEvents();
5956 mDispatcher->waitForIdle();
5957}
5958
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005959using InputDispatcherMonitorTest = InputDispatcherTest;
5960
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005961/**
5962 * Two entities that receive touch: A window, and a global monitor.
5963 * The touch goes to the window, and then the window disappears.
5964 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5965 * for the monitor, as well.
5966 * 1. foregroundWindow
5967 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5968 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005969TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005970 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5971 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005972 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005973
Prabir Pradhanfb549072023-10-05 19:17:36 +00005974 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005975
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005976 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005977 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005978 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005979 {100, 200}))
5980 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5981
5982 // Both the foreground window and the global monitor should receive the touch down
5983 window->consumeMotionDown();
5984 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5985
5986 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005987 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005988 ADISPLAY_ID_DEFAULT, {110, 200}))
5989 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5990
5991 window->consumeMotionMove();
5992 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5993
5994 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005995 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005996 window->consumeMotionCancel();
5997 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5998
5999 // If more events come in, there will be no more foreground window to send them to. This will
6000 // cause a cancel for the monitor, as well.
6001 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006002 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006003 ADISPLAY_ID_DEFAULT, {120, 200}))
6004 << "Injection should fail because the window was removed";
6005 window->assertNoEvents();
6006 // Global monitor now gets the cancel
6007 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6008}
6009
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006010TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07006011 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006012 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6013 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006014 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006015
Prabir Pradhanfb549072023-10-05 19:17:36 +00006016 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006017
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006018 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006019 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006020 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00006021 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006022 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006023}
6024
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006025TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00006026 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006027
Chris Yea209fde2020-07-22 13:54:51 -07006028 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006029 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6030 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006031 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006032
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006033 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006034 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006035 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08006036 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006037 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006038
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006039 // Pilfer pointers from the monitor.
6040 // This should not do anything and the window should continue to receive events.
6041 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00006042
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006043 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006044 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006045 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006046 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006047
6048 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6049 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006050}
6051
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006052TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07006053 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006054 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6055 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006056 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07006057 window->setWindowOffset(20, 40);
6058 window->setWindowTransform(0, 1, -1, 0);
6059
Prabir Pradhanfb549072023-10-05 19:17:36 +00006060 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07006061
6062 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006063 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07006064 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6065 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6066 MotionEvent* event = monitor.consumeMotion();
6067 // Even though window has transform, gesture monitor must not.
6068 ASSERT_EQ(ui::Transform(), event->getTransform());
6069}
6070
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006071TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00006072 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00006073 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00006074
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006075 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006076 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006077 << "Injection should fail if there is a monitor, but no touchable window";
6078 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00006079}
6080
chaviw81e2bb92019-12-18 15:03:51 -08006081TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006082 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006083 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6084 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08006085
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006086 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08006087
6088 NotifyMotionArgs motionArgs =
6089 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6090 ADISPLAY_ID_DEFAULT);
6091
Prabir Pradhan678438e2023-04-13 19:32:51 +00006092 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08006093 // Window should receive motion down event.
6094 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6095
6096 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08006097 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08006098 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6099 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
6100 motionArgs.pointerCoords[0].getX() - 10);
6101
Prabir Pradhan678438e2023-04-13 19:32:51 +00006102 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006103 window->consumeMotionMove(ADISPLAY_ID_DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08006104}
6105
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006106/**
6107 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
6108 * the device default right away. In the test scenario, we check both the default value,
6109 * and the action of enabling / disabling.
6110 */
6111TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07006112 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006113 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6114 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08006115 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006116
6117 // Set focused application.
6118 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006119 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006120
6121 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006122 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006123 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006124 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006125
6126 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006127 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006128 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006129 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006130
6131 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006132 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006133 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006134 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07006135 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006136 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006137 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006138 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006139
6140 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006141 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006142 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006143 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006144
6145 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006146 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006147 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006148 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07006149 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006150 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006151 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006152 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006153
6154 window->assertNoEvents();
6155}
6156
Gang Wange9087892020-01-07 12:17:14 -05006157TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006158 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006159 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6160 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05006161
6162 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006163 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05006164
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006165 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006166 setFocusedWindow(window);
6167
Harry Cutts33476232023-01-30 19:57:29 +00006168 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05006169
Prabir Pradhan678438e2023-04-13 19:32:51 +00006170 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
6171 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05006172
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006173 const KeyEvent& event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05006174
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006175 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(event);
Gang Wange9087892020-01-07 12:17:14 -05006176 ASSERT_NE(verified, nullptr);
6177 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
6178
6179 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
6180 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
6181 ASSERT_EQ(keyArgs.source, verified->source);
6182 ASSERT_EQ(keyArgs.displayId, verified->displayId);
6183
6184 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
6185
6186 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05006187 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006188 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05006189 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
6190 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
6191 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
6192 ASSERT_EQ(0, verifiedKey.repeatCount);
6193}
6194
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006195TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006196 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006197 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6198 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006199
6200 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6201
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006202 ui::Transform transform;
6203 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6204
6205 gui::DisplayInfo displayInfo;
6206 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6207 displayInfo.transform = transform;
6208
Patrick Williamsd828f302023-04-28 17:52:08 -05006209 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006210
Prabir Pradhan678438e2023-04-13 19:32:51 +00006211 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006212 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6213 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006214 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006215
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006216 const MotionEvent& event = window->consumeMotionEvent();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006217
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006218 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006219 ASSERT_NE(verified, nullptr);
6220 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
6221
6222 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
6223 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
6224 EXPECT_EQ(motionArgs.source, verified->source);
6225 EXPECT_EQ(motionArgs.displayId, verified->displayId);
6226
6227 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
6228
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006229 const vec2 rawXY =
6230 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
6231 motionArgs.pointerCoords[0].getXYValue());
6232 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
6233 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006234 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006235 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006236 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006237 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
6238 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
6239}
6240
chaviw09c8d2d2020-08-24 15:48:26 -07006241/**
6242 * Ensure that separate calls to sign the same data are generating the same key.
6243 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
6244 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
6245 * tests.
6246 */
6247TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
6248 KeyEvent event = getTestKeyEvent();
6249 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6250
6251 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
6252 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
6253 ASSERT_EQ(hmac1, hmac2);
6254}
6255
6256/**
6257 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6258 */
6259TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6260 KeyEvent event = getTestKeyEvent();
6261 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6262 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6263
6264 verifiedEvent.deviceId += 1;
6265 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6266
6267 verifiedEvent.source += 1;
6268 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6269
6270 verifiedEvent.eventTimeNanos += 1;
6271 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6272
6273 verifiedEvent.displayId += 1;
6274 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6275
6276 verifiedEvent.action += 1;
6277 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6278
6279 verifiedEvent.downTimeNanos += 1;
6280 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6281
6282 verifiedEvent.flags += 1;
6283 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6284
6285 verifiedEvent.keyCode += 1;
6286 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6287
6288 verifiedEvent.scanCode += 1;
6289 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6290
6291 verifiedEvent.metaState += 1;
6292 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6293
6294 verifiedEvent.repeatCount += 1;
6295 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6296}
6297
Vishnu Nair958da932020-08-21 17:12:37 -07006298TEST_F(InputDispatcherTest, SetFocusedWindow) {
6299 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6300 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006301 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006302 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006303 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006304 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6305
6306 // Top window is also focusable but is not granted focus.
6307 windowTop->setFocusable(true);
6308 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006309 mDispatcher->onWindowInfosChanged(
6310 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006311 setFocusedWindow(windowSecond);
6312
6313 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006314 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006315 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006316
6317 // Focused window should receive event.
6318 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6319 windowTop->assertNoEvents();
6320}
6321
6322TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
6323 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6324 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006325 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006326 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6327
6328 window->setFocusable(true);
6329 // Release channel for window is no longer valid.
6330 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006331 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006332 setFocusedWindow(window);
6333
6334 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006335 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006336
6337 // window channel is invalid, so it should not receive any input event.
6338 window->assertNoEvents();
6339}
6340
6341TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
6342 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6343 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006344 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006345 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006346 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6347
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006348 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006349 setFocusedWindow(window);
6350
6351 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006352 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006353
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006354 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006355 window->assertNoEvents();
6356}
6357
6358TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6359 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6360 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006361 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006362 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006363 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006364 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6365
6366 windowTop->setFocusable(true);
6367 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006368 mDispatcher->onWindowInfosChanged(
6369 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006370 setFocusedWindow(windowTop);
6371 windowTop->consumeFocusEvent(true);
6372
Chavi Weingarten847e8512023-03-29 00:26:09 +00006373 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006374 mDispatcher->onWindowInfosChanged(
6375 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006376 windowSecond->consumeFocusEvent(true);
6377 windowTop->consumeFocusEvent(false);
6378
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006379 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006380 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006381
6382 // Focused window should receive event.
6383 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6384}
6385
Chavi Weingarten847e8512023-03-29 00:26:09 +00006386TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006387 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6388 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006389 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006390 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006391 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006392 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6393
6394 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006395 windowSecond->setFocusable(false);
6396 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006397 mDispatcher->onWindowInfosChanged(
6398 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006399 setFocusedWindow(windowTop);
6400 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006401
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006402 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006403 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006404
6405 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006406 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006407 windowSecond->assertNoEvents();
6408}
6409
6410TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6411 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6412 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006413 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006414 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006415 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6416 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006417 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6418
6419 window->setFocusable(true);
6420 previousFocusedWindow->setFocusable(true);
6421 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006422 mDispatcher->onWindowInfosChanged(
6423 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006424 setFocusedWindow(previousFocusedWindow);
6425 previousFocusedWindow->consumeFocusEvent(true);
6426
6427 // Requesting focus on invisible window takes focus from currently focused window.
6428 setFocusedWindow(window);
6429 previousFocusedWindow->consumeFocusEvent(false);
6430
6431 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006432 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006433 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6434 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006435
6436 // Window does not get focus event or key down.
6437 window->assertNoEvents();
6438
6439 // Window becomes visible.
6440 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006441 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006442
6443 // Window receives focus event.
6444 window->consumeFocusEvent(true);
6445 // Focused window receives key down.
6446 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6447}
6448
Vishnu Nair599f1412021-06-21 10:39:58 -07006449TEST_F(InputDispatcherTest, DisplayRemoved) {
6450 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6451 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006452 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006453 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6454
6455 // window is granted focus.
6456 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006457 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006458 setFocusedWindow(window);
6459 window->consumeFocusEvent(true);
6460
6461 // When a display is removed window loses focus.
6462 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6463 window->consumeFocusEvent(false);
6464}
6465
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006466/**
6467 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6468 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6469 * of the 'slipperyEnterWindow'.
6470 *
6471 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6472 * a way so that the touched location is no longer covered by the top window.
6473 *
6474 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6475 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6476 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6477 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6478 * with ACTION_DOWN).
6479 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6480 * window moved itself away from the touched location and had Flag::SLIPPERY.
6481 *
6482 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6483 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6484 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6485 *
6486 * In this test, we ensure that the event received by the bottom window has
6487 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6488 */
6489TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006490 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006491 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006492
6493 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6494 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6495
6496 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006497 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006498 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006499 // Make sure this one overlaps the bottom window
6500 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6501 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6502 // one. Windows with the same owner are not considered to be occluding each other.
6503 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6504
6505 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006506 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006507 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6508
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006509 mDispatcher->onWindowInfosChanged(
6510 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006511
6512 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006513 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6514 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6515 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006516 slipperyExitWindow->consumeMotionDown();
6517 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006518 mDispatcher->onWindowInfosChanged(
6519 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006520
Prabir Pradhan678438e2023-04-13 19:32:51 +00006521 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6522 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6523 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006524
6525 slipperyExitWindow->consumeMotionCancel();
6526
6527 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6528 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6529}
6530
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006531/**
6532 * Two windows, one on the left and another on the right. The left window is slippery. The right
6533 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6534 * touch moves from the left window into the right window, the gesture should continue to go to the
6535 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6536 * reproduces a crash.
6537 */
6538TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6539 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6540
6541 sp<FakeWindowHandle> leftSlipperyWindow =
6542 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6543 leftSlipperyWindow->setSlippery(true);
6544 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6545
6546 sp<FakeWindowHandle> rightDropTouchesWindow =
6547 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6548 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6549 rightDropTouchesWindow->setDropInput(true);
6550
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006551 mDispatcher->onWindowInfosChanged(
6552 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006553
6554 // Start touch in the left window
6555 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6556 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6557 .build());
6558 leftSlipperyWindow->consumeMotionDown();
6559
6560 // And move it into the right window
6561 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6562 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6563 .build());
6564
6565 // Since the right window isn't eligible to receive input, touch does not slip.
6566 // The left window continues to receive the gesture.
6567 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6568 rightDropTouchesWindow->assertNoEvents();
6569}
6570
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006571/**
6572 * A single window is on screen first. Touch is injected into that window. Next, a second window
6573 * appears. Since the first window is slippery, touch will move from the first window to the second.
6574 */
6575TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6576 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6577 sp<FakeWindowHandle> originalWindow =
6578 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6579 originalWindow->setFrame(Rect(0, 0, 200, 200));
6580 originalWindow->setSlippery(true);
6581
6582 sp<FakeWindowHandle> appearingWindow =
6583 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6584 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6585
6586 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6587
6588 // Touch down on the original window
6589 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6590 injectMotionEvent(*mDispatcher,
6591 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6592 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6593 .build()));
6594 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6595
6596 // Now, a new window appears. This could be, for example, a notification shade that appears
6597 // after user starts to drag down on the launcher window.
6598 mDispatcher->onWindowInfosChanged(
6599 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6600 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6601 injectMotionEvent(*mDispatcher,
6602 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6603 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6604 .build()));
6605 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6606 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6607 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6608 injectMotionEvent(*mDispatcher,
6609 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6610 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6611 .build()));
6612 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6613
6614 originalWindow->assertNoEvents();
6615 appearingWindow->assertNoEvents();
6616}
6617
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006618TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006619 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006620 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6621
6622 sp<FakeWindowHandle> leftWindow =
6623 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6624 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006625 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006626
6627 sp<FakeWindowHandle> rightSpy =
6628 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6629 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006630 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006631 rightSpy->setSpy(true);
6632 rightSpy->setTrustedOverlay(true);
6633
6634 sp<FakeWindowHandle> rightWindow =
6635 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6636 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006637 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006638
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006639 mDispatcher->onWindowInfosChanged(
6640 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006641
6642 // Touch in the left window
6643 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6644 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6645 .build());
6646 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6647 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006648 ASSERT_NO_FATAL_FAILURE(
6649 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006650
6651 // Touch another finger over the right windows
6652 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6653 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6654 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6655 .build());
6656 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6657 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6658 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6659 mDispatcher->waitForIdle();
6660 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006661 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6662 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006663
6664 // Release finger over left window. The UP actions are not treated as device interaction.
6665 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6666 // is part of the UP action, we do not treat this as device interaction.
6667 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6668 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6669 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6670 .build());
6671 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6672 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6673 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6674 mDispatcher->waitForIdle();
6675 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6676
6677 // Move remaining finger
6678 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6679 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6680 .build());
6681 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6682 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6683 mDispatcher->waitForIdle();
6684 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006685 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006686
6687 // Release all fingers
6688 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6689 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6690 .build());
6691 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6692 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6693 mDispatcher->waitForIdle();
6694 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6695}
6696
6697TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6698 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6699
6700 sp<FakeWindowHandle> window =
6701 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6702 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006703 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006704
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006705 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006706 setFocusedWindow(window);
6707 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6708
6709 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6710 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6711 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006712 ASSERT_NO_FATAL_FAILURE(
6713 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006714
6715 // The UP actions are not treated as device interaction.
6716 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6717 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6718 mDispatcher->waitForIdle();
6719 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6720}
6721
Prabir Pradhan5893d362023-11-17 04:30:40 +00006722TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
6723 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6724
6725 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
6726 ADISPLAY_ID_DEFAULT);
6727 left->setFrame(Rect(0, 0, 100, 100));
6728 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
6729 "Right Window", ADISPLAY_ID_DEFAULT);
6730 right->setFrame(Rect(100, 0, 200, 100));
6731 sp<FakeWindowHandle> spy =
6732 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
6733 spy->setFrame(Rect(0, 0, 200, 100));
6734 spy->setTrustedOverlay(true);
6735 spy->setSpy(true);
6736
6737 mDispatcher->onWindowInfosChanged(
6738 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
6739
6740 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
6741 NotifyMotionArgs notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
6742 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
6743 mDispatcher->notifyMotion(notifyArgs);
6744
6745 const MotionEvent& leftEnter = left->consumeMotionEvent(
6746 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
6747 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6748
6749 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6750 Not(WithEventId(notifyArgs.id)),
6751 Not(WithEventId(leftEnter.getId())),
6752 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6753
6754 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
6755 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
6756 {PointF{150, 50}});
6757 mDispatcher->notifyMotion(notifyArgs);
6758
6759 const MotionEvent& leftExit = left->consumeMotionEvent(
6760 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
6761 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6762
6763 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6764 Not(WithEventId(notifyArgs.id)),
6765 Not(WithEventId(leftExit.getId())),
6766 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6767
6768 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
6769}
6770
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00006771class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
6772protected:
6773 std::shared_ptr<FakeApplicationHandle> mApp;
6774 sp<FakeWindowHandle> mWindow;
6775
6776 virtual void SetUp() override {
6777 InputDispatcherTest::SetUp();
6778
6779 mApp = std::make_shared<FakeApplicationHandle>();
6780
6781 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6782 mWindow->setFrame(Rect(0, 0, 100, 100));
6783
6784 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
6785 setFocusedWindow(mWindow);
6786 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
6787 }
6788
6789 void setFallback(int32_t keycode) {
6790 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
6791 return KeyEventBuilder(event).keyCode(keycode).build();
6792 });
6793 }
6794
6795 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006796 const KeyEvent& event = mWindow->consumeKey(handled);
6797 ASSERT_THAT(event, matcher);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00006798 }
6799};
6800
6801TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
6802 mDispatcher->notifyKey(
6803 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6804 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6805 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6806}
6807
6808TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
6809 mDispatcher->notifyKey(
6810 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6811 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6812 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6813}
6814
6815TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
6816 mDispatcher->notifyKey(
6817 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6818
6819 // Do not handle this key event.
6820 consumeKey(/*handled=*/false,
6821 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6822 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6823
6824 // Since the policy did not request any fallback to be generated, ensure there are no events.
6825 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6826}
6827
6828TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
6829 setFallback(AKEYCODE_B);
6830 mDispatcher->notifyKey(
6831 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6832
6833 // Do not handle this key event.
6834 consumeKey(/*handled=*/false,
6835 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6836
6837 // Since the key was not handled, ensure the fallback event was dispatched instead.
6838 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6839 consumeKey(/*handled=*/true,
6840 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6841 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6842
6843 // Release the original key, and ensure the fallback key is also released.
6844 mDispatcher->notifyKey(
6845 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6846 consumeKey(/*handled=*/false,
6847 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6848 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6849 consumeKey(/*handled=*/true,
6850 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6851 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6852
6853 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6854 mWindow->assertNoEvents();
6855}
6856
6857TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
6858 setFallback(AKEYCODE_B);
6859 mDispatcher->notifyKey(
6860 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6861
6862 // Do not handle this key event, but handle the fallback.
6863 consumeKey(/*handled=*/false,
6864 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6865 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6866 consumeKey(/*handled=*/true,
6867 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6868 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6869
6870 // Release the original key, and ensure the fallback key is also released.
6871 mDispatcher->notifyKey(
6872 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6873 // But this time, the app handles the original key.
6874 consumeKey(/*handled=*/true,
6875 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6876 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6877 // Ensure the fallback key is canceled.
6878 consumeKey(/*handled=*/true,
6879 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6880 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6881
6882 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6883 mWindow->assertNoEvents();
6884}
6885
6886TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
6887 setFallback(AKEYCODE_B);
6888 mDispatcher->notifyKey(
6889 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6890
6891 // Do not handle this key event.
6892 consumeKey(/*handled=*/false,
6893 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6894 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6895 // App does not handle the fallback either, so ensure another fallback is not generated.
6896 setFallback(AKEYCODE_C);
6897 consumeKey(/*handled=*/false,
6898 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6899 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6900
6901 // Release the original key, and ensure the fallback key is also released.
6902 setFallback(AKEYCODE_B);
6903 mDispatcher->notifyKey(
6904 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6905 consumeKey(/*handled=*/false,
6906 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6907 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6908 consumeKey(/*handled=*/false,
6909 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6910 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6911
6912 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6913 mWindow->assertNoEvents();
6914}
6915
6916TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
6917 setFallback(AKEYCODE_B);
6918 mDispatcher->notifyKey(
6919 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6920
6921 // Do not handle this key event, so fallback is generated.
6922 consumeKey(/*handled=*/false,
6923 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6924 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6925 consumeKey(/*handled=*/true,
6926 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6927 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6928
6929 // Release the original key, but assume the policy is misbehaving and it
6930 // generates an inconsistent fallback to the one from the DOWN event.
6931 setFallback(AKEYCODE_C);
6932 mDispatcher->notifyKey(
6933 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6934 consumeKey(/*handled=*/false,
6935 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6936 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6937 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
6938 consumeKey(/*handled=*/true,
6939 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6940 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6941
6942 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6943 mWindow->assertNoEvents();
6944}
6945
6946TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
6947 setFallback(AKEYCODE_B);
6948 mDispatcher->notifyKey(
6949 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6950
6951 // Do not handle this key event, so fallback is generated.
6952 consumeKey(/*handled=*/false,
6953 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6954 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6955 consumeKey(/*handled=*/true,
6956 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6957 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6958
6959 // The original key is canceled.
6960 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
6961 .keyCode(AKEYCODE_A)
6962 .addFlag(AKEY_EVENT_FLAG_CANCELED)
6963 .build());
6964 consumeKey(/*handled=*/false,
6965 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
6966 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
6967 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6968 // Ensure the fallback key is also canceled due to the original key being canceled.
6969 consumeKey(/*handled=*/true,
6970 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6971 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6972
6973 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6974 mWindow->assertNoEvents();
6975}
6976
Prabir Pradhanb13da8f2024-01-09 23:10:13 +00006977TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedDuringPolicyCall) {
6978 setFallback(AKEYCODE_B);
6979 mDispatcher->notifyKey(
6980 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6981
6982 // Do not handle this key event.
6983 consumeKey(/*handled=*/false,
6984 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6985 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6986 consumeKey(/*handled=*/true,
6987 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6988 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6989
6990 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
6991 // When the unhandled key is reported to the policy next, remove the input channel.
6992 mDispatcher->removeInputChannel(mWindow->getToken());
6993 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
6994 });
6995 // Release the original key, and let the app now handle the previously unhandled key.
6996 // This should result in the previously generated fallback key to be cancelled.
6997 // Since the policy was notified of the unhandled DOWN event earlier, it will also be notified
6998 // of the UP event for consistency. The Dispatcher calls into the policy from its own thread
6999 // without holding the lock, because it need to synchronously fetch the fallback key. While in
7000 // the policy call, we will now remove the input channel. Once the policy call returns, the
7001 // Dispatcher will no longer have a channel to send cancellation events to. Ensure this does
7002 // not cause any crashes.
7003 mDispatcher->notifyKey(
7004 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7005 consumeKey(/*handled=*/true,
7006 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7007 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7008}
7009
Garfield Tan1c7bc862020-01-28 13:24:04 -08007010class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
7011protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08007012 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
7013 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007014
Chris Yea209fde2020-07-22 13:54:51 -07007015 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007016 sp<FakeWindowHandle> mWindow;
7017
7018 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00007019 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00007020 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00007021 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09007022 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007023 ASSERT_EQ(OK, mDispatcher->start());
7024
7025 setUpWindow();
7026 }
7027
7028 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07007029 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007030 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007031
Vishnu Nair47074b82020-08-14 11:54:47 -07007032 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007033 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007034 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007035 mWindow->consumeFocusEvent(true);
7036 }
7037
Chris Ye2ad95392020-09-01 13:44:44 -07007038 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007039 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007040 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007041 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007042 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007043
7044 // Window should receive key down event.
7045 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7046 }
7047
7048 void expectKeyRepeatOnce(int32_t repeatCount) {
7049 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007050 mWindow->consumeKeyEvent(
7051 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007052 }
7053
Chris Ye2ad95392020-09-01 13:44:44 -07007054 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007055 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007056 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007057 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007058 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007059
7060 // Window should receive key down event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007061 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007062 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007063 }
7064};
7065
7066TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00007067 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007068 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7069 expectKeyRepeatOnce(repeatCount);
7070 }
7071}
7072
7073TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00007074 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007075 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7076 expectKeyRepeatOnce(repeatCount);
7077 }
Harry Cutts33476232023-01-30 19:57:29 +00007078 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007079 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08007080 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7081 expectKeyRepeatOnce(repeatCount);
7082 }
7083}
7084
7085TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007086 sendAndConsumeKeyDown(/*deviceId=*/1);
7087 expectKeyRepeatOnce(/*repeatCount=*/1);
7088 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007089 mWindow->assertNoEvents();
7090}
7091
7092TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007093 sendAndConsumeKeyDown(/*deviceId=*/1);
7094 expectKeyRepeatOnce(/*repeatCount=*/1);
7095 sendAndConsumeKeyDown(/*deviceId=*/2);
7096 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007097 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00007098 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007099 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00007100 expectKeyRepeatOnce(/*repeatCount=*/2);
7101 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07007102 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00007103 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007104 mWindow->assertNoEvents();
7105}
7106
7107TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007108 sendAndConsumeKeyDown(/*deviceId=*/1);
7109 expectKeyRepeatOnce(/*repeatCount=*/1);
7110 sendAndConsumeKeyDown(/*deviceId=*/2);
7111 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007112 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00007113 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007114 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08007115 mWindow->assertNoEvents();
7116}
7117
liushenxiang42232912021-05-21 20:24:09 +08007118TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
7119 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00007120 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007121 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08007122 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
7123 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
7124 mWindow->assertNoEvents();
7125}
7126
Garfield Tan1c7bc862020-01-28 13:24:04 -08007127TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007128 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007129 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007130 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007131 const KeyEvent& repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007132 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007133 IdGenerator::getSource(repeatEvent.getId()));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007134 }
7135}
7136
7137TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007138 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007139 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007140
7141 std::unordered_set<int32_t> idSet;
7142 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007143 const KeyEvent& repeatEvent = mWindow->consumeKey();
7144 int32_t id = repeatEvent.getId();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007145 EXPECT_EQ(idSet.end(), idSet.find(id));
7146 idSet.insert(id);
7147 }
7148}
7149
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007150/* Test InputDispatcher for MultiDisplay */
7151class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
7152public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007153 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007154 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08007155
Chris Yea209fde2020-07-22 13:54:51 -07007156 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007157 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007158 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007159
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007160 // Set focus window for primary display, but focused display would be second one.
7161 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07007162 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007163 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
7164
Vishnu Nair958da932020-08-21 17:12:37 -07007165 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007166 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08007167
Chris Yea209fde2020-07-22 13:54:51 -07007168 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007169 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007170 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007171 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007172 // Set focus display to second one.
7173 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
7174 // Set focus window for second display.
7175 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07007176 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007177 mDispatcher->onWindowInfosChanged(
7178 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007179 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007180 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007181 }
7182
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007183 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007184 InputDispatcherTest::TearDown();
7185
Chris Yea209fde2020-07-22 13:54:51 -07007186 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007187 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07007188 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007189 windowInSecondary.clear();
7190 }
7191
7192protected:
Chris Yea209fde2020-07-22 13:54:51 -07007193 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007194 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07007195 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007196 sp<FakeWindowHandle> windowInSecondary;
7197};
7198
7199TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
7200 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007201 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007202 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007203 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007204 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08007205 windowInSecondary->assertNoEvents();
7206
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007207 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007208 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007209 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007210 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007211 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007212 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08007213}
7214
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007215TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08007216 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007217 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007218 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007219 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007220 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08007221 windowInSecondary->assertNoEvents();
7222
7223 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007224 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007225 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007226 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007227 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08007228
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007229 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007230 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08007231
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007232 // Old focus should receive a cancel event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007233 windowInSecondary->consumeKeyUp(ADISPLAY_ID_NONE, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08007234
7235 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007236 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08007237 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007238 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08007239 windowInSecondary->assertNoEvents();
7240}
7241
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007242// Test per-display input monitors for motion event.
7243TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08007244 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007245 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007246 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007247 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007248
7249 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007250 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007251 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007252 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007253 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007254 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007255 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007256 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007257
7258 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007259 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007260 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007261 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007262 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007263 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007264 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08007265 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007266
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007267 // Lift up the touch from the second display
7268 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007269 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007270 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7271 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
7272 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
7273
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007274 // Test inject a non-pointer motion event.
7275 // If specific a display, it will dispatch to the focused window of particular display,
7276 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007277 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007278 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007279 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007280 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007281 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007282 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007283 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007284}
7285
7286// Test per-display input monitors for key event.
7287TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007288 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08007289 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007290 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007291 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007292 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007293
7294 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007295 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007296 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007297 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007298 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007299 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007300 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007301}
7302
Vishnu Nair958da932020-08-21 17:12:37 -07007303TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
7304 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007305 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007306 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007307 mDispatcher->onWindowInfosChanged(
7308 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
7309 *windowInSecondary->getInfo()},
7310 {},
7311 0,
7312 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007313 setFocusedWindow(secondWindowInPrimary);
7314 windowInPrimary->consumeFocusEvent(false);
7315 secondWindowInPrimary->consumeFocusEvent(true);
7316
7317 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007318 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7319 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007320 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007321 windowInPrimary->assertNoEvents();
7322 windowInSecondary->assertNoEvents();
7323 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7324}
7325
Arthur Hungdfd528e2021-12-08 13:23:04 +00007326TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
7327 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007328 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007329 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007330 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007331
7332 // Test touch down on primary display.
7333 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007334 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007335 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7336 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7337 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
7338
7339 // Test touch down on second display.
7340 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007341 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007342 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7343 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
7344 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
7345
7346 // Trigger cancel touch.
7347 mDispatcher->cancelCurrentTouch();
7348 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7349 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7350 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
7351 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
7352
7353 // Test inject a move motion event, no window/monitor should receive the event.
7354 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007355 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007356 ADISPLAY_ID_DEFAULT, {110, 200}))
7357 << "Inject motion event should return InputEventInjectionResult::FAILED";
7358 windowInPrimary->assertNoEvents();
7359 monitorInPrimary.assertNoEvents();
7360
7361 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007362 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007363 SECOND_DISPLAY_ID, {110, 200}))
7364 << "Inject motion event should return InputEventInjectionResult::FAILED";
7365 windowInSecondary->assertNoEvents();
7366 monitorInSecondary.assertNoEvents();
7367}
7368
Jackal Guof9696682018-10-05 12:23:23 +08007369class InputFilterTest : public InputDispatcherTest {
7370protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007371 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
7372 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08007373 NotifyMotionArgs motionArgs;
7374
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007375 motionArgs =
7376 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007377 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007378 motionArgs =
7379 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007380 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007381 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007382 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007383 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007384 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08007385 } else {
7386 mFakePolicy->assertFilterInputEventWasNotCalled();
7387 }
7388 }
7389
7390 void testNotifyKey(bool expectToBeFiltered) {
7391 NotifyKeyArgs keyArgs;
7392
7393 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007394 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007395 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007396 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007397 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007398
7399 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08007400 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007401 } else {
7402 mFakePolicy->assertFilterInputEventWasNotCalled();
7403 }
7404 }
7405};
7406
7407// Test InputFilter for MotionEvent
7408TEST_F(InputFilterTest, MotionEvent_InputFilter) {
7409 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007410 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7411 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007412
7413 // Enable InputFilter
7414 mDispatcher->setInputFilterEnabled(true);
7415 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007416 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
7417 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007418
7419 // Disable InputFilter
7420 mDispatcher->setInputFilterEnabled(false);
7421 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007422 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7423 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007424}
7425
7426// Test InputFilter for KeyEvent
7427TEST_F(InputFilterTest, KeyEvent_InputFilter) {
7428 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007429 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007430
7431 // Enable InputFilter
7432 mDispatcher->setInputFilterEnabled(true);
7433 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007434 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007435
7436 // Disable InputFilter
7437 mDispatcher->setInputFilterEnabled(false);
7438 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007439 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007440}
7441
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007442// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
7443// logical display coordinate space.
7444TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
7445 ui::Transform firstDisplayTransform;
7446 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7447 ui::Transform secondDisplayTransform;
7448 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
7449
7450 std::vector<gui::DisplayInfo> displayInfos(2);
7451 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
7452 displayInfos[0].transform = firstDisplayTransform;
7453 displayInfos[1].displayId = SECOND_DISPLAY_ID;
7454 displayInfos[1].transform = secondDisplayTransform;
7455
Patrick Williamsd828f302023-04-28 17:52:08 -05007456 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007457
7458 // Enable InputFilter
7459 mDispatcher->setInputFilterEnabled(true);
7460
7461 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007462 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
7463 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007464}
7465
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007466class InputFilterInjectionPolicyTest : public InputDispatcherTest {
7467protected:
7468 virtual void SetUp() override {
7469 InputDispatcherTest::SetUp();
7470
7471 /**
7472 * We don't need to enable input filter to test the injected event policy, but we enabled it
7473 * here to make the tests more realistic, since this policy only matters when inputfilter is
7474 * on.
7475 */
7476 mDispatcher->setInputFilterEnabled(true);
7477
7478 std::shared_ptr<InputApplicationHandle> application =
7479 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007480 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
7481 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007482
7483 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7484 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007485 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007486 setFocusedWindow(mWindow);
7487 mWindow->consumeFocusEvent(true);
7488 }
7489
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007490 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7491 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007492 KeyEvent event;
7493
7494 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7495 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
7496 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00007497 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007498 const int32_t additionalPolicyFlags =
7499 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
7500 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007501 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007502 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007503 policyFlags | additionalPolicyFlags));
7504
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007505 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007506 }
7507
7508 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7509 int32_t flags) {
7510 MotionEvent event;
7511 PointerProperties pointerProperties[1];
7512 PointerCoords pointerCoords[1];
7513 pointerProperties[0].clear();
7514 pointerProperties[0].id = 0;
7515 pointerCoords[0].clear();
7516 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
7517 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
7518
7519 ui::Transform identityTransform;
7520 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7521 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
7522 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
7523 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
7524 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07007525 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07007526 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007527 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007528
7529 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
7530 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007531 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007532 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007533 policyFlags | additionalPolicyFlags));
7534
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007535 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007536 }
7537
7538private:
7539 sp<FakeWindowHandle> mWindow;
7540};
7541
7542TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007543 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
7544 // filter. Without it, the event will no different from a regularly injected event, and the
7545 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00007546 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
7547 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007548}
7549
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007550TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007551 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007552 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007553 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
7554}
7555
7556TEST_F(InputFilterInjectionPolicyTest,
7557 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
7558 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007559 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007560 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007561}
7562
7563TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00007564 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
7565 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007566}
7567
chaviwfd6d3512019-03-25 13:23:49 -07007568class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007569 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07007570 InputDispatcherTest::SetUp();
7571
Chris Yea209fde2020-07-22 13:54:51 -07007572 std::shared_ptr<FakeApplicationHandle> application =
7573 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007574 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007575 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007576 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07007577
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007578 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007579 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007580 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07007581
7582 // Set focused application.
7583 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007584 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07007585
7586 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007587 mDispatcher->onWindowInfosChanged(
7588 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007589 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007590 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07007591 }
7592
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007593 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07007594 InputDispatcherTest::TearDown();
7595
7596 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007597 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07007598 }
7599
7600protected:
7601 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007602 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007603 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07007604};
7605
7606// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7607// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
7608// the onPointerDownOutsideFocus callback.
7609TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007610 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007611 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007612 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007613 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007614 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007615
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007616 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07007617 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
7618}
7619
7620// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
7621// DOWN on the window that doesn't have focus. Ensure no window received the
7622// onPointerDownOutsideFocus callback.
7623TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007624 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007625 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
7626 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007627 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007628 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007629
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007630 ASSERT_TRUE(mDispatcher->waitForIdle());
7631 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007632}
7633
7634// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
7635// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
7636TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007637 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007638 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007639 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007640 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007641
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007642 ASSERT_TRUE(mDispatcher->waitForIdle());
7643 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007644}
7645
7646// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7647// DOWN on the window that already has focus. Ensure no window received the
7648// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007649TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007650 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007651 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007652 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007653 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007654 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007655
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007656 ASSERT_TRUE(mDispatcher->waitForIdle());
7657 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007658}
7659
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007660// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
7661// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
7662TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
7663 const MotionEvent event =
7664 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
7665 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007666 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007667 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
7668 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007669 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007670 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7671 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7672
7673 ASSERT_TRUE(mDispatcher->waitForIdle());
7674 mFakePolicy->assertOnPointerDownWasNotCalled();
7675 // Ensure that the unfocused window did not receive any FOCUS events.
7676 mUnfocusedWindow->assertNoEvents();
7677}
7678
chaviwaf87b3e2019-10-01 16:59:28 -07007679// These tests ensures we can send touch events to a single client when there are multiple input
7680// windows that point to the same client token.
7681class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
7682 virtual void SetUp() override {
7683 InputDispatcherTest::SetUp();
7684
Chris Yea209fde2020-07-22 13:54:51 -07007685 std::shared_ptr<FakeApplicationHandle> application =
7686 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007687 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
7688 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07007689 mWindow1->setFrame(Rect(0, 0, 100, 100));
7690
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00007691 mWindow2 = mWindow1->clone(ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07007692 mWindow2->setFrame(Rect(100, 100, 200, 200));
7693
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007694 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007695 }
7696
7697protected:
7698 sp<FakeWindowHandle> mWindow1;
7699 sp<FakeWindowHandle> mWindow2;
7700
7701 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05007702 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07007703 vec2 vals = windowInfo->transform.transform(point.x, point.y);
7704 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07007705 }
7706
7707 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
7708 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007709 const std::string name = window->getName();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007710 const MotionEvent& motionEvent =
7711 window->consumeMotionEvent(WithMotionAction(expectedAction));
chaviwaf87b3e2019-10-01 16:59:28 -07007712
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007713 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07007714
7715 for (size_t i = 0; i < points.size(); i++) {
7716 float expectedX = points[i].x;
7717 float expectedY = points[i].y;
7718
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007719 EXPECT_EQ(expectedX, motionEvent.getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007720 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007721 << ", got " << motionEvent.getX(i);
7722 EXPECT_EQ(expectedY, motionEvent.getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007723 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007724 << ", got " << motionEvent.getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07007725 }
7726 }
chaviw9eaa22c2020-07-01 16:21:27 -07007727
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007728 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07007729 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007730 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
7731 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07007732
7733 // Always consume from window1 since it's the window that has the InputReceiver
7734 consumeMotionEvent(mWindow1, action, expectedPoints);
7735 }
chaviwaf87b3e2019-10-01 16:59:28 -07007736};
7737
7738TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
7739 // Touch Window 1
7740 PointF touchedPoint = {10, 10};
7741 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007742 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007743
7744 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007745 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007746
7747 // Touch Window 2
7748 touchedPoint = {150, 150};
7749 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007750 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007751}
7752
chaviw9eaa22c2020-07-01 16:21:27 -07007753TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
7754 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07007755 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007756 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007757
7758 // Touch Window 1
7759 PointF touchedPoint = {10, 10};
7760 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007761 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007762 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007763 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007764
7765 // Touch Window 2
7766 touchedPoint = {150, 150};
7767 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007768 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
7769 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007770
chaviw9eaa22c2020-07-01 16:21:27 -07007771 // Update the transform so rotation is set
7772 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007773 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007774 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
7775 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007776}
7777
chaviw9eaa22c2020-07-01 16:21:27 -07007778TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007779 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007780 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007781
7782 // Touch Window 1
7783 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7784 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007785 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007786
7787 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007788 touchedPoints.push_back(PointF{150, 150});
7789 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007790 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007791
chaviw9eaa22c2020-07-01 16:21:27 -07007792 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007793 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007794 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007795
chaviw9eaa22c2020-07-01 16:21:27 -07007796 // Update the transform so rotation is set for Window 2
7797 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007798 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007799 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007800 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007801}
7802
chaviw9eaa22c2020-07-01 16:21:27 -07007803TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007804 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007805 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007806
7807 // Touch Window 1
7808 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7809 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007810 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007811
7812 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007813 touchedPoints.push_back(PointF{150, 150});
7814 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007815
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007816 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007817
7818 // Move both windows
7819 touchedPoints = {{20, 20}, {175, 175}};
7820 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7821 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7822
chaviw9eaa22c2020-07-01 16:21:27 -07007823 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007824
chaviw9eaa22c2020-07-01 16:21:27 -07007825 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007826 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007827 expectedPoints.pop_back();
7828
7829 // Touch Window 2
7830 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007831 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007832 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007833 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007834
7835 // Move both windows
7836 touchedPoints = {{20, 20}, {175, 175}};
7837 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7838 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7839
7840 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007841}
7842
7843TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
7844 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007845 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007846
7847 // Touch Window 1
7848 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7849 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007850 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007851
7852 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007853 touchedPoints.push_back(PointF{150, 150});
7854 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007855
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007856 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007857
7858 // Move both windows
7859 touchedPoints = {{20, 20}, {175, 175}};
7860 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7861 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7862
chaviw9eaa22c2020-07-01 16:21:27 -07007863 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007864}
7865
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007866/**
7867 * When one of the windows is slippery, the touch should not slip into the other window with the
7868 * same input channel.
7869 */
7870TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
7871 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007872 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007873
7874 // Touch down in window 1
7875 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7876 ADISPLAY_ID_DEFAULT, {{50, 50}}));
7877 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
7878
7879 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
7880 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
7881 // getting generated.
7882 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7883 ADISPLAY_ID_DEFAULT, {{150, 150}}));
7884
7885 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
7886}
7887
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007888/**
7889 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
7890 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
7891 * that the pointer is hovering over may have a different transform.
7892 */
7893TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007894 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007895
7896 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007897 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
7898 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7899 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007900 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7901 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007902 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007903 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7904 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
7905 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007906 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
7907 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7908 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
7909}
7910
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007911class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
7912 virtual void SetUp() override {
7913 InputDispatcherTest::SetUp();
7914
Chris Yea209fde2020-07-22 13:54:51 -07007915 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007916 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007917 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
7918 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007919 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007920 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07007921 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007922
7923 // Set focused application.
7924 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7925
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007926 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007927 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007928 mWindow->consumeFocusEvent(true);
7929 }
7930
7931 virtual void TearDown() override {
7932 InputDispatcherTest::TearDown();
7933 mWindow.clear();
7934 }
7935
7936protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007937 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07007938 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007939 sp<FakeWindowHandle> mWindow;
7940 static constexpr PointF WINDOW_LOCATION = {20, 20};
7941
7942 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08007943 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
7944 .x(WINDOW_LOCATION.x)
7945 .y(WINDOW_LOCATION.y);
7946 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7947 .pointer(touchingPointer)
7948 .build());
7949 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7950 .pointer(touchingPointer)
7951 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007952 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007953
7954 sp<FakeWindowHandle> addSpyWindow() {
7955 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007956 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007957 spy->setTrustedOverlay(true);
7958 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007959 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007960 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007961 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007962 return spy;
7963 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007964};
7965
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007966// Send a tap and respond, which should not cause an ANR.
7967TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
7968 tapOnWindow();
7969 mWindow->consumeMotionDown();
7970 mWindow->consumeMotionUp();
7971 ASSERT_TRUE(mDispatcher->waitForIdle());
7972 mFakePolicy->assertNotifyAnrWasNotCalled();
7973}
7974
7975// Send a regular key and respond, which should not cause an ANR.
7976TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007977 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007978 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7979 ASSERT_TRUE(mDispatcher->waitForIdle());
7980 mFakePolicy->assertNotifyAnrWasNotCalled();
7981}
7982
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007983TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
7984 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007985 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007986 mWindow->consumeFocusEvent(false);
7987
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007988 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007989 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7990 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00007991 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007992 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007993 // Key will not go to window because we have no focused window.
7994 // The 'no focused window' ANR timer should start instead.
7995
7996 // Now, the focused application goes away.
7997 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
7998 // The key should get dropped and there should be no ANR.
7999
8000 ASSERT_TRUE(mDispatcher->waitForIdle());
8001 mFakePolicy->assertNotifyAnrWasNotCalled();
8002}
8003
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008004// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008005// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8006// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008007TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008008 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008009 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008010 WINDOW_LOCATION));
8011
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008012 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
8013 ASSERT_TRUE(sequenceNum);
8014 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008015 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008016
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008017 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008018 mWindow->consumeMotionEvent(
8019 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008020 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008021 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008022}
8023
8024// Send a key to the app and have the app not respond right away.
8025TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
8026 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008027 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008028 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
8029 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008030 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008031 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008032 ASSERT_TRUE(mDispatcher->waitForIdle());
8033}
8034
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008035// We have a focused application, but no focused window
8036TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008037 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008038 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008039 mWindow->consumeFocusEvent(false);
8040
8041 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008042 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008043 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008044 WINDOW_LOCATION));
8045 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
8046 mDispatcher->waitForIdle();
8047 mFakePolicy->assertNotifyAnrWasNotCalled();
8048
8049 // Once a focused event arrives, we get an ANR for this application
8050 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8051 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008052 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008053 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008054 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008055 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008056 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07008057 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008058 ASSERT_TRUE(mDispatcher->waitForIdle());
8059}
8060
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008061/**
8062 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
8063 * there will not be an ANR.
8064 */
8065TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
8066 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008067 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008068 mWindow->consumeFocusEvent(false);
8069
8070 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07008071 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
8072 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008073 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
8074 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
8075
8076 // Define a valid key down event that is stale (too old).
8077 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00008078 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00008079 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008080
8081 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
8082
8083 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00008084 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008085 InputEventInjectionSync::WAIT_FOR_RESULT,
8086 INJECT_EVENT_TIMEOUT, policyFlags);
8087 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
8088 << "Injection should fail because the event is stale";
8089
8090 ASSERT_TRUE(mDispatcher->waitForIdle());
8091 mFakePolicy->assertNotifyAnrWasNotCalled();
8092 mWindow->assertNoEvents();
8093}
8094
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008095// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008096// Make sure that we don't notify policy twice about the same ANR.
8097TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008098 const std::chrono::duration appTimeout = 400ms;
8099 mApplication->setDispatchingTimeout(appTimeout);
8100 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8101
Vishnu Nair47074b82020-08-14 11:54:47 -07008102 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008103 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008104 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008105
8106 // Once a focused event arrives, we get an ANR for this application
8107 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8108 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008109 const std::chrono::duration eventInjectionTimeout = 100ms;
8110 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008111 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008112 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008113 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
8114 /*allowKeyRepeat=*/false);
8115 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
8116 << "result=" << ftl::enum_string(result);
8117 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
8118 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
8119 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
8120 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008121
Vishnu Naire4df8752022-09-08 09:17:55 -07008122 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008123 // ANR should not be raised again. It is up to policy to do that if it desires.
8124 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008125
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008126 // If we now get a focused window, the ANR should stop, but the policy handles that via
8127 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008128 ASSERT_TRUE(mDispatcher->waitForIdle());
8129}
8130
8131// We have a focused application, but no focused window
8132TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008133 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008134 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008135 mWindow->consumeFocusEvent(false);
8136
8137 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008138 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008139
Vishnu Naire4df8752022-09-08 09:17:55 -07008140 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8141 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008142
8143 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008144 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008145 ASSERT_TRUE(mDispatcher->waitForIdle());
8146 mWindow->assertNoEvents();
8147}
8148
8149/**
8150 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
8151 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
8152 * If we process 1 of the events, but ANR on the second event with the same timestamp,
8153 * the ANR mechanism should still work.
8154 *
8155 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
8156 * DOWN event, while not responding on the second one.
8157 */
8158TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
8159 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008160 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008161 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8162 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8163 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008164 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008165
8166 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008167 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008168 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8169 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8170 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008171 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008172
8173 // We have now sent down and up. Let's consume first event and then ANR on the second.
8174 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8175 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008176 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008177}
8178
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008179// A spy window can receive an ANR
8180TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
8181 sp<FakeWindowHandle> spy = addSpyWindow();
8182
8183 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008184 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008185 WINDOW_LOCATION));
8186 mWindow->consumeMotionDown();
8187
8188 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
8189 ASSERT_TRUE(sequenceNum);
8190 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008191 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008192
8193 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008194 spy->consumeMotionEvent(
8195 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008196 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008197 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008198}
8199
8200// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008201// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008202TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
8203 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008204
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008205 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008206 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008207 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008208 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008209
8210 // Stuck on the ACTION_UP
8211 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008212 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008213
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008214 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008215 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008216 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8217 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008218
8219 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8220 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008221 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008222 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008223 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008224}
8225
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008226// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008227// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008228TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
8229 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008230
8231 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008232 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8233 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008234
8235 mWindow->consumeMotionDown();
8236 // Stuck on the ACTION_UP
8237 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008238 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008239
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008240 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008241 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008242 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8243 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008244
8245 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8246 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008247 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008248 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008249 spy->assertNoEvents();
8250}
8251
8252TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008253 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008254
Prabir Pradhanfb549072023-10-05 19:17:36 +00008255 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008256
8257 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008258 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008259 WINDOW_LOCATION));
8260
8261 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8262 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
8263 ASSERT_TRUE(consumeSeq);
8264
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008265 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
8266 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008267
8268 monitor.finishEvent(*consumeSeq);
8269 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
8270
8271 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008272 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008273}
8274
8275// If a window is unresponsive, then you get anr. if the window later catches up and starts to
8276// process events, you don't get an anr. When the window later becomes unresponsive again, you
8277// get an ANR again.
8278// 1. tap -> block on ACTION_UP -> receive ANR
8279// 2. consume all pending events (= queue becomes healthy again)
8280// 3. tap again -> block on ACTION_UP again -> receive ANR second time
8281TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
8282 tapOnWindow();
8283
8284 mWindow->consumeMotionDown();
8285 // Block on ACTION_UP
8286 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008287 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008288 mWindow->consumeMotionUp(); // Now the connection should be healthy again
8289 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008290 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008291 mWindow->assertNoEvents();
8292
8293 tapOnWindow();
8294 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008295 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008296 mWindow->consumeMotionUp();
8297
8298 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008299 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008300 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008301 mWindow->assertNoEvents();
8302}
8303
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008304// If a connection remains unresponsive for a while, make sure policy is only notified once about
8305// it.
8306TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008307 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008308 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008309 WINDOW_LOCATION));
8310
8311 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008312 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008313 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008314 // 'notifyConnectionUnresponsive' should only be called once per connection
8315 mFakePolicy->assertNotifyAnrWasNotCalled();
8316 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008317 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008318 mWindow->consumeMotionEvent(
8319 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008320 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008321 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008322 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008323 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008324}
8325
8326/**
8327 * 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 -07008328 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008329 *
8330 * Warning!!!
8331 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8332 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008333 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008334 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8335 *
8336 * If that value changes, this test should also change.
8337 */
8338TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
8339 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008340 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008341
8342 tapOnWindow();
8343 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
8344 ASSERT_TRUE(downSequenceNum);
8345 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
8346 ASSERT_TRUE(upSequenceNum);
8347 // Don't finish the events yet, and send a key
8348 // Injection will "succeed" because we will eventually give up and send the key to the focused
8349 // window even if motions are still being processed. But because the injection timeout is short,
8350 // we will receive INJECTION_TIMED_OUT as the result.
8351
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008352 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008353 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8354 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008355 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008356 // Key will not be sent to the window, yet, because the window is still processing events
8357 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008358 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
8359 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8360 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8361 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008362
8363 std::this_thread::sleep_for(500ms);
8364 // if we wait long enough though, dispatcher will give up, and still send the key
8365 // to the focused window, even though we have not yet finished the motion event
8366 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8367 mWindow->finishEvent(*downSequenceNum);
8368 mWindow->finishEvent(*upSequenceNum);
8369}
8370
8371/**
8372 * If a window is processing a motion event, and then a key event comes in, the key event should
8373 * not go to the focused window until the motion is processed.
8374 * If then a new motion comes in, then the pending key event should be going to the currently
8375 * focused window right away.
8376 */
8377TEST_F(InputDispatcherSingleWindowAnr,
8378 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
8379 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008380 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008381
8382 tapOnWindow();
8383 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
8384 ASSERT_TRUE(downSequenceNum);
8385 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
8386 ASSERT_TRUE(upSequenceNum);
8387 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008388 mDispatcher->notifyKey(
8389 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
8390 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8391 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008392 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008393 // Make sure the `assertNoEvents` check doesn't take too long. It uses
8394 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8395 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8396 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008397
8398 // Now tap down again. It should cause the pending key to go to the focused window right away.
8399 tapOnWindow();
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008400 mWindow->consumeKeyEvent(WithKeyAction(AKEY_EVENT_ACTION_DOWN)); // it doesn't matter that we
8401 // haven't ack'd the other events yet. We can finish events in any order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008402 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
8403 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008404 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8405 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008406 mWindow->assertNoEvents();
8407}
8408
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07008409/**
8410 * Send an event to the app and have the app not respond right away.
8411 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8412 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
8413 * At some point, the window becomes responsive again.
8414 * Ensure that subsequent events get dropped, and the next gesture is delivered.
8415 */
8416TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
8417 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8418 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
8419 .build());
8420
8421 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
8422 ASSERT_TRUE(sequenceNum);
8423 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8424 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
8425
8426 mWindow->finishEvent(*sequenceNum);
8427 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
8428 ASSERT_TRUE(mDispatcher->waitForIdle());
8429 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
8430
8431 // Now that the window is responsive, let's continue the gesture.
8432 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8433 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8434 .build());
8435
8436 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8437 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8438 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8439 .build());
8440
8441 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8442 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8443 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8444 .build());
8445 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8446 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8447 .build());
8448 // We already canceled this pointer, so the window shouldn't get any new events.
8449 mWindow->assertNoEvents();
8450
8451 // Start another one.
8452 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8453 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
8454 .build());
8455 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8456}
8457
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008458class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
8459 virtual void SetUp() override {
8460 InputDispatcherTest::SetUp();
8461
Chris Yea209fde2020-07-22 13:54:51 -07008462 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008463 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008464 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
8465 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008466 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008467 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008468 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008469
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008470 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
8471 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008472 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008473 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008474
8475 // Set focused application.
8476 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07008477 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008478
8479 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008480 mDispatcher->onWindowInfosChanged(
8481 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008482 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008483 mFocusedWindow->consumeFocusEvent(true);
8484 }
8485
8486 virtual void TearDown() override {
8487 InputDispatcherTest::TearDown();
8488
8489 mUnfocusedWindow.clear();
8490 mFocusedWindow.clear();
8491 }
8492
8493protected:
Chris Yea209fde2020-07-22 13:54:51 -07008494 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008495 sp<FakeWindowHandle> mUnfocusedWindow;
8496 sp<FakeWindowHandle> mFocusedWindow;
8497 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
8498 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
8499 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
8500
8501 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
8502
8503 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
8504
8505private:
8506 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008507 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008508 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008509 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008510 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008511 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008512 location));
8513 }
8514};
8515
8516// If we have 2 windows that are both unresponsive, the one with the shortest timeout
8517// should be ANR'd first.
8518TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008519 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008520 injectMotionEvent(*mDispatcher,
8521 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8522 AINPUT_SOURCE_TOUCHSCREEN)
8523 .pointer(PointerBuilder(0, ToolType::FINGER)
8524 .x(FOCUSED_WINDOW_LOCATION.x)
8525 .y(FOCUSED_WINDOW_LOCATION.y))
8526 .build()));
8527 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8528 injectMotionEvent(*mDispatcher,
8529 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
8530 AINPUT_SOURCE_TOUCHSCREEN)
8531 .pointer(PointerBuilder(0, ToolType::FINGER)
8532 .x(FOCUSED_WINDOW_LOCATION.x)
8533 .y(FOCUSED_WINDOW_LOCATION.y))
8534 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008535 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008536 mFocusedWindow->consumeMotionUp();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008537 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008538 // We consumed all events, so no ANR
8539 ASSERT_TRUE(mDispatcher->waitForIdle());
8540 mFakePolicy->assertNotifyAnrWasNotCalled();
8541
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008542 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008543 injectMotionEvent(*mDispatcher,
8544 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8545 AINPUT_SOURCE_TOUCHSCREEN)
8546 .pointer(PointerBuilder(0, ToolType::FINGER)
8547 .x(FOCUSED_WINDOW_LOCATION.x)
8548 .y(FOCUSED_WINDOW_LOCATION.y))
8549 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008550 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
8551 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008552
8553 const std::chrono::duration timeout =
8554 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008555 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008556
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008557 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008558 mFocusedWindow->consumeMotionDown();
8559 // This cancel is generated because the connection was unresponsive
8560 mFocusedWindow->consumeMotionCancel();
8561 mFocusedWindow->assertNoEvents();
8562 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008563 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008564 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8565 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008566 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008567}
8568
8569// If we have 2 windows with identical timeouts that are both unresponsive,
8570// it doesn't matter which order they should have ANR.
8571// But we should receive ANR for both.
8572TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
8573 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008574 mUnfocusedWindow->setDispatchingTimeout(
8575 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008576 mDispatcher->onWindowInfosChanged(
8577 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008578
8579 tapOnFocusedWindow();
8580 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008581 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008582 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
8583 mFocusedWindow->getDispatchingTimeout(
8584 DISPATCHING_TIMEOUT)),
8585 mFakePolicy->getUnresponsiveWindowToken(0ms)};
8586
8587 ASSERT_THAT(anrConnectionTokens,
8588 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8589 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008590
8591 ASSERT_TRUE(mDispatcher->waitForIdle());
8592 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008593
8594 mFocusedWindow->consumeMotionDown();
8595 mFocusedWindow->consumeMotionUp();
8596 mUnfocusedWindow->consumeMotionOutside();
8597
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008598 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
8599 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008600
8601 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008602 ASSERT_THAT(responsiveTokens,
8603 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8604 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008605 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008606}
8607
8608// If a window is already not responding, the second tap on the same window should be ignored.
8609// We should also log an error to account for the dropped event (not tested here).
8610// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
8611TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
8612 tapOnFocusedWindow();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008613 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008614 // Receive the events, but don't respond
8615 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
8616 ASSERT_TRUE(downEventSequenceNum);
8617 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
8618 ASSERT_TRUE(upEventSequenceNum);
8619 const std::chrono::duration timeout =
8620 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008621 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008622
8623 // Tap once again
8624 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008625 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008626 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008627 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008628 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008629 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008630 FOCUSED_WINDOW_LOCATION));
8631 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
8632 // valid touch target
8633 mUnfocusedWindow->assertNoEvents();
8634
8635 // Consume the first tap
8636 mFocusedWindow->finishEvent(*downEventSequenceNum);
8637 mFocusedWindow->finishEvent(*upEventSequenceNum);
8638 ASSERT_TRUE(mDispatcher->waitForIdle());
8639 // The second tap did not go to the focused window
8640 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008641 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08008642 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8643 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008644 mFakePolicy->assertNotifyAnrWasNotCalled();
8645}
8646
8647// If you tap outside of all windows, there will not be ANR
8648TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008649 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008650 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008651 LOCATION_OUTSIDE_ALL_WINDOWS));
8652 ASSERT_TRUE(mDispatcher->waitForIdle());
8653 mFakePolicy->assertNotifyAnrWasNotCalled();
8654}
8655
8656// Since the focused window is paused, tapping on it should not produce any events
8657TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
8658 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008659 mDispatcher->onWindowInfosChanged(
8660 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008661
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008662 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008663 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008664 FOCUSED_WINDOW_LOCATION));
8665
8666 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
8667 ASSERT_TRUE(mDispatcher->waitForIdle());
8668 // Should not ANR because the window is paused, and touches shouldn't go to it
8669 mFakePolicy->assertNotifyAnrWasNotCalled();
8670
8671 mFocusedWindow->assertNoEvents();
8672 mUnfocusedWindow->assertNoEvents();
8673}
8674
8675/**
8676 * 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 -07008677 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008678 * If a different window becomes focused at this time, the key should go to that window instead.
8679 *
8680 * Warning!!!
8681 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8682 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008683 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008684 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8685 *
8686 * If that value changes, this test should also change.
8687 */
8688TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
8689 // Set a long ANR timeout to prevent it from triggering
8690 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008691 mDispatcher->onWindowInfosChanged(
8692 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008693
8694 tapOnUnfocusedWindow();
8695 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
8696 ASSERT_TRUE(downSequenceNum);
8697 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
8698 ASSERT_TRUE(upSequenceNum);
8699 // Don't finish the events yet, and send a key
8700 // Injection will succeed because we will eventually give up and send the key to the focused
8701 // window even if motions are still being processed.
8702
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008703 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008704 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8705 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008706 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008707 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008708 // and the key remains pending, waiting for the touch events to be processed.
8709 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
8710 // under the hood.
8711 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8712 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008713
8714 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07008715 mFocusedWindow->setFocusable(false);
8716 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008717 mDispatcher->onWindowInfosChanged(
8718 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008719 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008720
8721 // Focus events should precede the key events
8722 mUnfocusedWindow->consumeFocusEvent(true);
8723 mFocusedWindow->consumeFocusEvent(false);
8724
8725 // Finish the tap events, which should unblock dispatcher
8726 mUnfocusedWindow->finishEvent(*downSequenceNum);
8727 mUnfocusedWindow->finishEvent(*upSequenceNum);
8728
8729 // Now that all queues are cleared and no backlog in the connections, the key event
8730 // can finally go to the newly focused "mUnfocusedWindow".
8731 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8732 mFocusedWindow->assertNoEvents();
8733 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008734 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008735}
8736
8737// When the touch stream is split across 2 windows, and one of them does not respond,
8738// then ANR should be raised and the touch should be canceled for the unresponsive window.
8739// The other window should not be affected by that.
8740TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
8741 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00008742 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8743 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8744 {FOCUSED_WINDOW_LOCATION}));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008745 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008746
8747 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00008748 mDispatcher->notifyMotion(
8749 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8750 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008751
8752 const std::chrono::duration timeout =
8753 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008754 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008755
8756 mUnfocusedWindow->consumeMotionDown();
8757 mFocusedWindow->consumeMotionDown();
8758 // Focused window may or may not receive ACTION_MOVE
8759 // But it should definitely receive ACTION_CANCEL due to the ANR
8760 InputEvent* event;
8761 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
8762 ASSERT_TRUE(moveOrCancelSequenceNum);
8763 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
8764 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008765 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008766 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
8767 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
8768 mFocusedWindow->consumeMotionCancel();
8769 } else {
8770 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
8771 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008772 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008773 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8774 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008775
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008776 mUnfocusedWindow->assertNoEvents();
8777 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008778 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008779}
8780
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008781/**
8782 * If we have no focused window, and a key comes in, we start the ANR timer.
8783 * The focused application should add a focused window before the timer runs out to prevent ANR.
8784 *
8785 * If the user touches another application during this time, the key should be dropped.
8786 * Next, if a new focused window comes in, without toggling the focused application,
8787 * then no ANR should occur.
8788 *
8789 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
8790 * but in some cases the policy may not update the focused application.
8791 */
8792TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
8793 std::shared_ptr<FakeApplicationHandle> focusedApplication =
8794 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07008795 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008796 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
8797 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
8798 mFocusedWindow->setFocusable(false);
8799
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008800 mDispatcher->onWindowInfosChanged(
8801 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008802 mFocusedWindow->consumeFocusEvent(false);
8803
8804 // Send a key. The ANR timer should start because there is no focused window.
8805 // 'focusedApplication' will get blamed if this timer completes.
8806 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008807 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008808 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8809 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00008810 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008811 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008812
8813 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
8814 // then the injected touches won't cause the focused event to get dropped.
8815 // The dispatcher only checks for whether the queue should be pruned upon queueing.
8816 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
8817 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
8818 // For this test, it means that the key would get delivered to the window once it becomes
8819 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008820 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008821
8822 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00008823 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8824 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8825 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008826
8827 // We do not consume the motion right away, because that would require dispatcher to first
8828 // process (== drop) the key event, and by that time, ANR will be raised.
8829 // Set the focused window first.
8830 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008831 mDispatcher->onWindowInfosChanged(
8832 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008833 setFocusedWindow(mFocusedWindow);
8834 mFocusedWindow->consumeFocusEvent(true);
8835 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
8836 // to another application. This could be a bug / behaviour in the policy.
8837
8838 mUnfocusedWindow->consumeMotionDown();
8839
8840 ASSERT_TRUE(mDispatcher->waitForIdle());
8841 // Should not ANR because we actually have a focused window. It was just added too slowly.
8842 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
8843}
8844
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -08008845/**
8846 * If we are pruning input queue, we should never drop pointer events. Otherwise, we risk having
8847 * an inconsistent event stream inside the dispatcher. In this test, we make sure that the
8848 * dispatcher doesn't prune pointer events incorrectly.
8849 *
8850 * This test reproduces a crash in InputDispatcher.
8851 * To reproduce the crash, we need to simulate the conditions for "pruning input queue" to occur.
8852 *
8853 * Keep the currently focused application (mApplication), and have no focused window.
8854 * We set up two additional windows:
8855 * 1) The navigation bar window. This simulates the system "NavigationBar", which is used in the
8856 * 3-button navigation mode. This window injects a BACK button when it's touched. 2) The application
8857 * window. This window is not focusable, but is touchable.
8858 *
8859 * We first touch the navigation bar, which causes it to inject a key. Since there's no focused
8860 * window, the dispatcher doesn't process this key, and all other events inside dispatcher are now
8861 * blocked. The dispatcher is waiting for 'mApplication' to add a focused window.
8862 *
8863 * Now, we touch "Another window". This window is owned by a different application than
8864 * 'mApplication'. This causes the dispatcher to stop waiting for 'mApplication' to add a focused
8865 * window. Now, the "pruning input queue" behaviour should kick in, and the dispatcher should start
8866 * dropping the events from its queue. Ensure that no crash occurs.
8867 *
8868 * In this test, we are setting long timeouts to prevent ANRs and events dropped due to being stale.
8869 * This does not affect the test running time.
8870 */
8871TEST_F(InputDispatcherMultiWindowAnr, PruningInputQueueShouldNotDropPointerEvents) {
8872 std::shared_ptr<FakeApplicationHandle> systemUiApplication =
8873 std::make_shared<FakeApplicationHandle>();
8874 systemUiApplication->setDispatchingTimeout(3000ms);
8875 mFakePolicy->setStaleEventTimeout(3000ms);
8876 sp<FakeWindowHandle> navigationBar =
8877 sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
8878 ADISPLAY_ID_DEFAULT);
8879 navigationBar->setFocusable(false);
8880 navigationBar->setWatchOutsideTouch(true);
8881 navigationBar->setFrame(Rect(0, 0, 100, 100));
8882
8883 mApplication->setDispatchingTimeout(3000ms);
8884 // 'mApplication' is already focused, but we call it again here to make it explicit.
8885 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8886
8887 std::shared_ptr<FakeApplicationHandle> anotherApplication =
8888 std::make_shared<FakeApplicationHandle>();
8889 sp<FakeWindowHandle> appWindow =
8890 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
8891 ADISPLAY_ID_DEFAULT);
8892 appWindow->setFocusable(false);
8893 appWindow->setFrame(Rect(100, 100, 200, 200));
8894
8895 mDispatcher->onWindowInfosChanged(
8896 {{*navigationBar->getInfo(), *appWindow->getInfo()}, {}, 0, 0});
8897 // 'mFocusedWindow' is no longer in the dispatcher window list, and therefore loses focus
8898 mFocusedWindow->consumeFocusEvent(false);
8899
8900 // Touch down the navigation bar. It consumes the touch and injects a key into the dispatcher
8901 // in response.
8902 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8903 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8904 .build());
8905 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8906
8907 // Key will not be sent anywhere because we have no focused window. It will remain pending.
8908 // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
8909 InputEventInjectionResult result =
8910 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8911 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
8912 /*allowKeyRepeat=*/false);
8913 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
8914
8915 // Finish the gesture - lift up finger and inject ACTION_UP key event
8916 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8917 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8918 .build());
8919 result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8920 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
8921 /*allowKeyRepeat=*/false);
8922 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
8923 // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
8924 // getting any events yet.
8925 navigationBar->assertNoEvents();
8926
8927 // Now touch "Another window". This touch is going to a different application than the one we
8928 // are waiting for (which is 'mApplication').
8929 // This should cause the dispatcher to drop the pending focus-dispatched events (like the key
8930 // trying to be injected) and to continue processing the rest of the events in the original
8931 // order.
8932 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8933 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
8934 .build());
8935 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_UP));
8936 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
8937 appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8938
8939 appWindow->assertNoEvents();
8940 navigationBar->assertNoEvents();
8941}
8942
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008943// These tests ensure we cannot send touch events to a window that's positioned behind a window
8944// that has feature NO_INPUT_CHANNEL.
8945// Layout:
8946// Top (closest to user)
8947// mNoInputWindow (above all windows)
8948// mBottomWindow
8949// Bottom (furthest from user)
8950class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
8951 virtual void SetUp() override {
8952 InputDispatcherTest::SetUp();
8953
8954 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008955 mNoInputWindow =
8956 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8957 "Window without input channel", ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00008958 /*createInputChannel=*/false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008959 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008960 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
8961 // It's perfectly valid for this window to not have an associated input channel
8962
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008963 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
8964 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008965 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
8966
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008967 mDispatcher->onWindowInfosChanged(
8968 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008969 }
8970
8971protected:
8972 std::shared_ptr<FakeApplicationHandle> mApplication;
8973 sp<FakeWindowHandle> mNoInputWindow;
8974 sp<FakeWindowHandle> mBottomWindow;
8975};
8976
8977TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
8978 PointF touchedPoint = {10, 10};
8979
Prabir Pradhan678438e2023-04-13 19:32:51 +00008980 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8981 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8982 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008983
8984 mNoInputWindow->assertNoEvents();
8985 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
8986 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
8987 // and therefore should prevent mBottomWindow from receiving touches
8988 mBottomWindow->assertNoEvents();
8989}
8990
8991/**
8992 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
8993 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
8994 */
8995TEST_F(InputDispatcherMultiWindowOcclusionTests,
8996 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008997 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8998 "Window with input channel and NO_INPUT_CHANNEL",
8999 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009000
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009001 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009002 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009003 mDispatcher->onWindowInfosChanged(
9004 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009005
9006 PointF touchedPoint = {10, 10};
9007
Prabir Pradhan678438e2023-04-13 19:32:51 +00009008 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9009 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9010 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009011
9012 mNoInputWindow->assertNoEvents();
9013 mBottomWindow->assertNoEvents();
9014}
9015
Vishnu Nair958da932020-08-21 17:12:37 -07009016class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
9017protected:
9018 std::shared_ptr<FakeApplicationHandle> mApp;
9019 sp<FakeWindowHandle> mWindow;
9020 sp<FakeWindowHandle> mMirror;
9021
9022 virtual void SetUp() override {
9023 InputDispatcherTest::SetUp();
9024 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009025 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009026 mMirror = mWindow->clone(ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07009027 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
9028 mWindow->setFocusable(true);
9029 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009030 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009031 }
9032};
9033
9034TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
9035 // Request focus on a mirrored window
9036 setFocusedWindow(mMirror);
9037
9038 // window gets focused
9039 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009040 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009041 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009042 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
9043}
9044
9045// A focused & mirrored window remains focused only if the window and its mirror are both
9046// focusable.
9047TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
9048 setFocusedWindow(mMirror);
9049
9050 // window gets focused
9051 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009052 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009053 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009054 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009055 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009056 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009057 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9058
9059 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009060 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009061
9062 // window loses focus since one of the windows associated with the token in not focusable
9063 mWindow->consumeFocusEvent(false);
9064
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009065 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009066 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009067 mWindow->assertNoEvents();
9068}
9069
9070// A focused & mirrored window remains focused until the window and its mirror both become
9071// invisible.
9072TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
9073 setFocusedWindow(mMirror);
9074
9075 // window gets focused
9076 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009077 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009078 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009079 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009080 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009081 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009082 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9083
9084 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009085 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009086
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009087 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009088 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009089 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009090 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009091 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009092 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9093
9094 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009095 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009096
9097 // window loses focus only after all windows associated with the token become invisible.
9098 mWindow->consumeFocusEvent(false);
9099
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009100 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009101 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009102 mWindow->assertNoEvents();
9103}
9104
9105// A focused & mirrored window remains focused until both windows are removed.
9106TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
9107 setFocusedWindow(mMirror);
9108
9109 // window gets focused
9110 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009111 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009112 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009113 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009114 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009115 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009116 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9117
9118 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009119 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009120
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009121 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009122 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009123 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009124 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009125 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009126 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9127
9128 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009129 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009130 mWindow->consumeFocusEvent(false);
9131
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009132 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009133 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009134 mWindow->assertNoEvents();
9135}
9136
9137// Focus request can be pending until one window becomes visible.
9138TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
9139 // Request focus on an invisible mirror.
9140 mWindow->setVisible(false);
9141 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009142 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009143 setFocusedWindow(mMirror);
9144
9145 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009146 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009147 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9148 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07009149
9150 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009151 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009152
9153 // window gets focused
9154 mWindow->consumeFocusEvent(true);
9155 // window gets the pending key event
9156 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9157}
Prabir Pradhan99987712020-11-10 18:43:05 -08009158
9159class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
9160protected:
9161 std::shared_ptr<FakeApplicationHandle> mApp;
9162 sp<FakeWindowHandle> mWindow;
9163 sp<FakeWindowHandle> mSecondWindow;
9164
9165 void SetUp() override {
9166 InputDispatcherTest::SetUp();
9167 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009168 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009169 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009170 mSecondWindow =
9171 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009172 mSecondWindow->setFocusable(true);
9173
9174 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009175 mDispatcher->onWindowInfosChanged(
9176 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08009177
9178 setFocusedWindow(mWindow);
9179 mWindow->consumeFocusEvent(true);
9180 }
9181
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009182 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009183 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08009184 }
9185
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009186 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
9187 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08009188 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009189 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
9190 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009191 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009192 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08009193 }
9194};
9195
9196TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
9197 // Ensure that capture cannot be obtained for unfocused windows.
9198 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
9199 mFakePolicy->assertSetPointerCaptureNotCalled();
9200 mSecondWindow->assertNoEvents();
9201
9202 // Ensure that capture can be enabled from the focus window.
9203 requestAndVerifyPointerCapture(mWindow, true);
9204
9205 // Ensure that capture cannot be disabled from a window that does not have capture.
9206 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
9207 mFakePolicy->assertSetPointerCaptureNotCalled();
9208
9209 // Ensure that capture can be disabled from the window with capture.
9210 requestAndVerifyPointerCapture(mWindow, false);
9211}
9212
9213TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009214 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009215
9216 setFocusedWindow(mSecondWindow);
9217
9218 // Ensure that the capture disabled event was sent first.
9219 mWindow->consumeCaptureEvent(false);
9220 mWindow->consumeFocusEvent(false);
9221 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009222 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009223
9224 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009225 notifyPointerCaptureChanged({});
9226 notifyPointerCaptureChanged(request);
9227 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08009228 mWindow->assertNoEvents();
9229 mSecondWindow->assertNoEvents();
9230 mFakePolicy->assertSetPointerCaptureNotCalled();
9231}
9232
9233TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009234 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009235
9236 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009237 notifyPointerCaptureChanged({});
9238 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009239
9240 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009241 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009242 mWindow->consumeCaptureEvent(false);
9243 mWindow->assertNoEvents();
9244}
9245
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009246TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
9247 requestAndVerifyPointerCapture(mWindow, true);
9248
9249 // The first window loses focus.
9250 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009251 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009252 mWindow->consumeCaptureEvent(false);
9253
9254 // Request Pointer Capture from the second window before the notification from InputReader
9255 // arrives.
9256 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009257 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009258
9259 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009260 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009261
9262 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009263 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009264
9265 mSecondWindow->consumeFocusEvent(true);
9266 mSecondWindow->consumeCaptureEvent(true);
9267}
9268
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009269TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
9270 // App repeatedly enables and disables capture.
9271 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9272 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9273 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9274 mFakePolicy->assertSetPointerCaptureCalled(false);
9275 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9276 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9277
9278 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
9279 // first request is now stale, this should do nothing.
9280 notifyPointerCaptureChanged(firstRequest);
9281 mWindow->assertNoEvents();
9282
9283 // InputReader notifies that the second request was enabled.
9284 notifyPointerCaptureChanged(secondRequest);
9285 mWindow->consumeCaptureEvent(true);
9286}
9287
Prabir Pradhan7092e262022-05-03 16:51:09 +00009288TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
9289 requestAndVerifyPointerCapture(mWindow, true);
9290
9291 // App toggles pointer capture off and on.
9292 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9293 mFakePolicy->assertSetPointerCaptureCalled(false);
9294
9295 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9296 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9297
9298 // InputReader notifies that the latest "enable" request was processed, while skipping over the
9299 // preceding "disable" request.
9300 notifyPointerCaptureChanged(enableRequest);
9301
9302 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
9303 // any notifications.
9304 mWindow->assertNoEvents();
9305}
9306
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009307/**
9308 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
9309 * mouse movements don't affect the previous mouse hovering state.
9310 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
9311 * HOVER_MOVE events).
9312 */
9313TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
9314 // Mouse hover on the window
9315 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
9316 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9317 .build());
9318 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9319 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9320 .build());
9321
9322 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
9323 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
9324
9325 // Start pointer capture
9326 requestAndVerifyPointerCapture(mWindow, true);
9327
9328 // Send some relative mouse movements and receive them in the window.
9329 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
9330 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
9331 .build());
9332 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
9333 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
9334
9335 // Stop pointer capture
9336 requestAndVerifyPointerCapture(mWindow, false);
9337
9338 // Continue hovering on the window
9339 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9340 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
9341 .build());
9342 mWindow->consumeMotionEvent(
9343 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
9344
9345 mWindow->assertNoEvents();
9346}
9347
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009348class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
9349protected:
9350 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00009351
9352 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
9353 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
9354
9355 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
9356 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9357
9358 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
9359 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
9360 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9361 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
9362 MAXIMUM_OBSCURING_OPACITY);
9363
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009364 static constexpr gui::Uid TOUCHED_APP_UID{10001};
9365 static constexpr gui::Uid APP_B_UID{10002};
9366 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009367
9368 sp<FakeWindowHandle> mTouchWindow;
9369
9370 virtual void SetUp() override {
9371 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009372 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009373 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
9374 }
9375
9376 virtual void TearDown() override {
9377 InputDispatcherTest::TearDown();
9378 mTouchWindow.clear();
9379 }
9380
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009381 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05009382 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009383 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009384 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009385 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009386 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009387 return window;
9388 }
9389
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009390 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009391 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
9392 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009393 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009394 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009395 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009396 return window;
9397 }
9398
9399 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009400 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9401 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9402 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009403 }
9404};
9405
9406TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009407 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009408 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009409 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009410
9411 touch();
9412
9413 mTouchWindow->assertNoEvents();
9414}
9415
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009416TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00009417 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
9418 const sp<FakeWindowHandle>& w =
9419 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009420 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009421
9422 touch();
9423
9424 mTouchWindow->assertNoEvents();
9425}
9426
9427TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009428 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
9429 const sp<FakeWindowHandle>& w =
9430 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009431 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009432
9433 touch();
9434
9435 w->assertNoEvents();
9436}
9437
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009438TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009439 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009440 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009441
9442 touch();
9443
9444 mTouchWindow->consumeAnyMotionDown();
9445}
9446
9447TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009448 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009449 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009450 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009451 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009452
9453 touch({PointF{100, 100}});
9454
9455 mTouchWindow->consumeAnyMotionDown();
9456}
9457
9458TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009459 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009460 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009461 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009462
9463 touch();
9464
9465 mTouchWindow->consumeAnyMotionDown();
9466}
9467
9468TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
9469 const sp<FakeWindowHandle>& w =
9470 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009471 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009472
9473 touch();
9474
9475 mTouchWindow->consumeAnyMotionDown();
9476}
9477
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009478TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
9479 const sp<FakeWindowHandle>& w =
9480 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009481 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009482
9483 touch();
9484
9485 w->assertNoEvents();
9486}
9487
9488/**
9489 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
9490 * inside) while letting them pass-through. Note that even though touch passes through the occluding
9491 * window, the occluding window will still receive ACTION_OUTSIDE event.
9492 */
9493TEST_F(InputDispatcherUntrustedTouchesTest,
9494 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
9495 const sp<FakeWindowHandle>& w =
9496 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009497 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009498 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009499
9500 touch();
9501
9502 w->consumeMotionOutside();
9503}
9504
9505TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
9506 const sp<FakeWindowHandle>& w =
9507 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009508 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009509 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009510
9511 touch();
9512
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009513 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009514}
9515
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009516TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009517 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009518 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9519 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009520 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009521
9522 touch();
9523
9524 mTouchWindow->consumeAnyMotionDown();
9525}
9526
9527TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
9528 const sp<FakeWindowHandle>& w =
9529 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9530 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009531 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009532
9533 touch();
9534
9535 mTouchWindow->consumeAnyMotionDown();
9536}
9537
9538TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009539 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009540 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9541 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009542 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009543
9544 touch();
9545
9546 mTouchWindow->assertNoEvents();
9547}
9548
9549TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
9550 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
9551 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009552 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9553 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009554 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009555 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9556 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009557 mDispatcher->onWindowInfosChanged(
9558 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009559
9560 touch();
9561
9562 mTouchWindow->assertNoEvents();
9563}
9564
9565TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
9566 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
9567 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009568 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9569 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009570 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009571 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9572 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009573 mDispatcher->onWindowInfosChanged(
9574 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009575
9576 touch();
9577
9578 mTouchWindow->consumeAnyMotionDown();
9579}
9580
9581TEST_F(InputDispatcherUntrustedTouchesTest,
9582 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
9583 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009584 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9585 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009586 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009587 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9588 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009589 mDispatcher->onWindowInfosChanged(
9590 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009591
9592 touch();
9593
9594 mTouchWindow->consumeAnyMotionDown();
9595}
9596
9597TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
9598 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009599 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9600 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009601 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009602 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9603 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009604 mDispatcher->onWindowInfosChanged(
9605 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009606
9607 touch();
9608
9609 mTouchWindow->assertNoEvents();
9610}
9611
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009612TEST_F(InputDispatcherUntrustedTouchesTest,
9613 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
9614 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009615 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9616 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009617 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009618 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9619 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009620 mDispatcher->onWindowInfosChanged(
9621 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009622
9623 touch();
9624
9625 mTouchWindow->assertNoEvents();
9626}
9627
9628TEST_F(InputDispatcherUntrustedTouchesTest,
9629 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
9630 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009631 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9632 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009633 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009634 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9635 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009636 mDispatcher->onWindowInfosChanged(
9637 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009638
9639 touch();
9640
9641 mTouchWindow->consumeAnyMotionDown();
9642}
9643
9644TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
9645 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009646 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9647 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009648 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009649
9650 touch();
9651
9652 mTouchWindow->consumeAnyMotionDown();
9653}
9654
9655TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
9656 const sp<FakeWindowHandle>& w =
9657 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009658 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009659
9660 touch();
9661
9662 mTouchWindow->consumeAnyMotionDown();
9663}
9664
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009665TEST_F(InputDispatcherUntrustedTouchesTest,
9666 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
9667 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9668 const sp<FakeWindowHandle>& w =
9669 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009670 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009671
9672 touch();
9673
9674 mTouchWindow->assertNoEvents();
9675}
9676
9677TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
9678 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9679 const sp<FakeWindowHandle>& w =
9680 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009681 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009682
9683 touch();
9684
9685 mTouchWindow->consumeAnyMotionDown();
9686}
9687
9688TEST_F(InputDispatcherUntrustedTouchesTest,
9689 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
9690 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
9691 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009692 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9693 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009694 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009695
9696 touch();
9697
9698 mTouchWindow->consumeAnyMotionDown();
9699}
9700
9701TEST_F(InputDispatcherUntrustedTouchesTest,
9702 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
9703 const sp<FakeWindowHandle>& w1 =
9704 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9705 OPACITY_BELOW_THRESHOLD);
9706 const sp<FakeWindowHandle>& w2 =
9707 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9708 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009709 mDispatcher->onWindowInfosChanged(
9710 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009711
9712 touch();
9713
9714 mTouchWindow->assertNoEvents();
9715}
9716
9717/**
9718 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
9719 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
9720 * (which alone would result in allowing touches) does not affect the blocking behavior.
9721 */
9722TEST_F(InputDispatcherUntrustedTouchesTest,
9723 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
9724 const sp<FakeWindowHandle>& wB =
9725 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9726 OPACITY_BELOW_THRESHOLD);
9727 const sp<FakeWindowHandle>& wC =
9728 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9729 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009730 mDispatcher->onWindowInfosChanged(
9731 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009732
9733 touch();
9734
9735 mTouchWindow->assertNoEvents();
9736}
9737
9738/**
9739 * This test is testing that a window from a different UID but with same application token doesn't
9740 * block the touch. Apps can share the application token for close UI collaboration for example.
9741 */
9742TEST_F(InputDispatcherUntrustedTouchesTest,
9743 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
9744 const sp<FakeWindowHandle>& w =
9745 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
9746 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009747 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009748
9749 touch();
9750
9751 mTouchWindow->consumeAnyMotionDown();
9752}
9753
arthurhungb89ccb02020-12-30 16:19:01 +08009754class InputDispatcherDragTests : public InputDispatcherTest {
9755protected:
9756 std::shared_ptr<FakeApplicationHandle> mApp;
9757 sp<FakeWindowHandle> mWindow;
9758 sp<FakeWindowHandle> mSecondWindow;
9759 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009760 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009761 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
9762 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08009763
9764 void SetUp() override {
9765 InputDispatcherTest::SetUp();
9766 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009767 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009768 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009769
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009770 mSecondWindow =
9771 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009772 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009773
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009774 mSpyWindow =
9775 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009776 mSpyWindow->setSpy(true);
9777 mSpyWindow->setTrustedOverlay(true);
9778 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
9779
arthurhungb89ccb02020-12-30 16:19:01 +08009780 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009781 mDispatcher->onWindowInfosChanged(
9782 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
9783 {},
9784 0,
9785 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009786 }
9787
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009788 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
9789 switch (fromSource) {
9790 case AINPUT_SOURCE_TOUCHSCREEN:
9791 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009792 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009793 ADISPLAY_ID_DEFAULT, {50, 50}))
9794 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9795 break;
9796 case AINPUT_SOURCE_STYLUS:
9797 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009798 injectMotionEvent(*mDispatcher,
9799 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9800 AINPUT_SOURCE_STYLUS)
9801 .buttonState(
9802 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
9803 .pointer(PointerBuilder(0, ToolType::STYLUS)
9804 .x(50)
9805 .y(50))
9806 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009807 break;
9808 case AINPUT_SOURCE_MOUSE:
9809 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009810 injectMotionEvent(*mDispatcher,
9811 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9812 AINPUT_SOURCE_MOUSE)
9813 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
9814 .pointer(PointerBuilder(MOUSE_POINTER_ID,
9815 ToolType::MOUSE)
9816 .x(50)
9817 .y(50))
9818 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009819 break;
9820 default:
9821 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
9822 }
arthurhungb89ccb02020-12-30 16:19:01 +08009823
9824 // Window should receive motion event.
9825 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009826 // Spy window should also receive motion event
9827 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00009828 }
9829
9830 // Start performing drag, we will create a drag window and transfer touch to it.
9831 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
9832 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009833 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00009834 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009835 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00009836 }
arthurhungb89ccb02020-12-30 16:19:01 +08009837
9838 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009839 mDragWindow =
9840 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009841 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009842 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
9843 *mWindow->getInfo(), *mSecondWindow->getInfo()},
9844 {},
9845 0,
9846 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009847
9848 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00009849 bool transferred =
9850 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00009851 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00009852 if (transferred) {
9853 mWindow->consumeMotionCancel();
9854 mDragWindow->consumeMotionDown();
9855 }
9856 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08009857 }
9858};
9859
9860TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009861 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08009862
9863 // Move on window.
9864 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009865 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009866 ADISPLAY_ID_DEFAULT, {50, 50}))
9867 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9868 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9869 mWindow->consumeDragEvent(false, 50, 50);
9870 mSecondWindow->assertNoEvents();
9871
9872 // Move to another window.
9873 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009874 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009875 ADISPLAY_ID_DEFAULT, {150, 50}))
9876 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9877 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9878 mWindow->consumeDragEvent(true, 150, 50);
9879 mSecondWindow->consumeDragEvent(false, 50, 50);
9880
9881 // Move back to original window.
9882 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009883 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009884 ADISPLAY_ID_DEFAULT, {50, 50}))
9885 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9886 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9887 mWindow->consumeDragEvent(false, 50, 50);
9888 mSecondWindow->consumeDragEvent(true, -50, 50);
9889
9890 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009891 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9892 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08009893 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9894 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9895 mWindow->assertNoEvents();
9896 mSecondWindow->assertNoEvents();
9897}
9898
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009899TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009900 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009901
9902 // No cancel event after drag start
9903 mSpyWindow->assertNoEvents();
9904
9905 const MotionEvent secondFingerDownEvent =
9906 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9907 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009908 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9909 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009910 .build();
9911 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009912 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009913 InputEventInjectionSync::WAIT_FOR_RESULT))
9914 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9915
9916 // Receives cancel for first pointer after next pointer down
9917 mSpyWindow->consumeMotionCancel();
9918 mSpyWindow->consumeMotionDown();
9919
9920 mSpyWindow->assertNoEvents();
9921}
9922
arthurhungf452d0b2021-01-06 00:19:52 +08009923TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009924 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08009925
9926 // Move on window.
9927 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009928 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009929 ADISPLAY_ID_DEFAULT, {50, 50}))
9930 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9931 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9932 mWindow->consumeDragEvent(false, 50, 50);
9933 mSecondWindow->assertNoEvents();
9934
9935 // Move to another window.
9936 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009937 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009938 ADISPLAY_ID_DEFAULT, {150, 50}))
9939 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9940 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9941 mWindow->consumeDragEvent(true, 150, 50);
9942 mSecondWindow->consumeDragEvent(false, 50, 50);
9943
9944 // drop to another window.
9945 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009946 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +08009947 {150, 50}))
9948 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9949 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009950 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08009951 mWindow->assertNoEvents();
9952 mSecondWindow->assertNoEvents();
9953}
9954
Vaibhav Devmurari110ba322023-11-17 10:47:16 +00009955TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
9956 startDrag();
9957
9958 // No cancel event after drag start
9959 mSpyWindow->assertNoEvents();
9960
9961 const MotionEvent secondFingerDownEvent =
9962 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9963 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
9964 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9965 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
9966 .build();
9967 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9968 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9969 InputEventInjectionSync::WAIT_FOR_RESULT))
9970 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9971
9972 // Receives cancel for first pointer after next pointer down
9973 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -08009974 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +00009975 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
9976
9977 mSpyWindow->assertNoEvents();
9978
9979 // Spy window calls pilfer pointers
9980 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
9981 mDragWindow->assertNoEvents();
9982
9983 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -08009984 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +00009985 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
9986 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
9987 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
9988 .build();
9989 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -08009990 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +00009991 InputEventInjectionSync::WAIT_FOR_RESULT))
9992 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9993
9994 // Drag window should still receive the new event
9995 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
9996 mDragWindow->assertNoEvents();
9997}
9998
arthurhung6d4bed92021-03-17 11:59:33 +08009999TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010000 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +080010001
10002 // Move on window and keep button pressed.
10003 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010004 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010005 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10006 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010007 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010008 .build()))
10009 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10010 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10011 mWindow->consumeDragEvent(false, 50, 50);
10012 mSecondWindow->assertNoEvents();
10013
10014 // Move to another window and release button, expect to drop item.
10015 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010016 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010017 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10018 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010019 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010020 .build()))
10021 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10022 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10023 mWindow->assertNoEvents();
10024 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010025 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +080010026
10027 // nothing to the window.
10028 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010029 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010030 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
10031 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010032 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010033 .build()))
10034 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10035 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10036 mWindow->assertNoEvents();
10037 mSecondWindow->assertNoEvents();
10038}
10039
Arthur Hung54745652022-04-20 07:17:41 +000010040TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010041 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +080010042
10043 // Set second window invisible.
10044 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010045 mDispatcher->onWindowInfosChanged(
10046 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +080010047
10048 // Move on window.
10049 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010050 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010051 ADISPLAY_ID_DEFAULT, {50, 50}))
10052 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10053 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10054 mWindow->consumeDragEvent(false, 50, 50);
10055 mSecondWindow->assertNoEvents();
10056
10057 // Move to another window.
10058 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010059 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010060 ADISPLAY_ID_DEFAULT, {150, 50}))
10061 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10062 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10063 mWindow->consumeDragEvent(true, 150, 50);
10064 mSecondWindow->assertNoEvents();
10065
10066 // drop to another window.
10067 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010068 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010069 {150, 50}))
10070 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10071 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010072 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010073 mWindow->assertNoEvents();
10074 mSecondWindow->assertNoEvents();
10075}
10076
Arthur Hung54745652022-04-20 07:17:41 +000010077TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010078 // Ensure window could track pointerIds if it didn't support split touch.
10079 mWindow->setPreventSplitting(true);
10080
Arthur Hung54745652022-04-20 07:17:41 +000010081 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010082 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010083 {50, 50}))
10084 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10085 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10086
10087 const MotionEvent secondFingerDownEvent =
10088 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10089 .displayId(ADISPLAY_ID_DEFAULT)
10090 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010091 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10092 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010093 .build();
10094 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010095 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010096 InputEventInjectionSync::WAIT_FOR_RESULT))
10097 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010098 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +000010099
10100 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010101 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010102}
10103
10104TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
10105 // First down on second window.
10106 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010107 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010108 {150, 50}))
10109 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10110
10111 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10112
10113 // Second down on first window.
10114 const MotionEvent secondFingerDownEvent =
10115 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10116 .displayId(ADISPLAY_ID_DEFAULT)
10117 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010118 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10119 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010120 .build();
10121 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010122 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010123 InputEventInjectionSync::WAIT_FOR_RESULT))
10124 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10125 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10126
10127 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010128 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010129
10130 // Move on window.
10131 const MotionEvent secondFingerMoveEvent =
10132 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10133 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010134 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10135 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010136 .build();
10137 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010138 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010139 InputEventInjectionSync::WAIT_FOR_RESULT));
10140 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10141 mWindow->consumeDragEvent(false, 50, 50);
10142 mSecondWindow->consumeMotionMove();
10143
10144 // Release the drag pointer should perform drop.
10145 const MotionEvent secondFingerUpEvent =
10146 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10147 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010148 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10149 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010150 .build();
10151 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010152 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010153 InputEventInjectionSync::WAIT_FOR_RESULT));
10154 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010155 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000010156 mWindow->assertNoEvents();
10157 mSecondWindow->consumeMotionMove();
10158}
10159
Arthur Hung3915c1f2022-05-31 07:17:17 +000010160TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010161 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000010162
10163 // Update window of second display.
10164 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010165 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010166 mDispatcher->onWindowInfosChanged(
10167 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10168 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10169 {},
10170 0,
10171 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010172
10173 // Let second display has a touch state.
10174 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010175 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010176 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10177 AINPUT_SOURCE_TOUCHSCREEN)
10178 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010179 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000010180 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000010181 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010182 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010183 mDispatcher->onWindowInfosChanged(
10184 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10185 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10186 {},
10187 0,
10188 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010189
10190 // Move on window.
10191 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010192 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010193 ADISPLAY_ID_DEFAULT, {50, 50}))
10194 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10195 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10196 mWindow->consumeDragEvent(false, 50, 50);
10197 mSecondWindow->assertNoEvents();
10198
10199 // Move to another window.
10200 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010201 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010202 ADISPLAY_ID_DEFAULT, {150, 50}))
10203 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10204 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10205 mWindow->consumeDragEvent(true, 150, 50);
10206 mSecondWindow->consumeDragEvent(false, 50, 50);
10207
10208 // drop to another window.
10209 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010210 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010211 {150, 50}))
10212 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10213 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010214 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000010215 mWindow->assertNoEvents();
10216 mSecondWindow->assertNoEvents();
10217}
10218
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010219TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
10220 startDrag(true, AINPUT_SOURCE_MOUSE);
10221 // Move on window.
10222 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010223 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010224 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10225 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010226 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010227 .x(50)
10228 .y(50))
10229 .build()))
10230 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10231 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10232 mWindow->consumeDragEvent(false, 50, 50);
10233 mSecondWindow->assertNoEvents();
10234
10235 // Move to another window.
10236 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010237 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010238 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10239 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010240 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010241 .x(150)
10242 .y(50))
10243 .build()))
10244 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10245 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10246 mWindow->consumeDragEvent(true, 150, 50);
10247 mSecondWindow->consumeDragEvent(false, 50, 50);
10248
10249 // drop to another window.
10250 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010251 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010252 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
10253 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010254 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010255 .x(150)
10256 .y(50))
10257 .build()))
10258 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10259 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010260 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010261 mWindow->assertNoEvents();
10262 mSecondWindow->assertNoEvents();
10263}
10264
Linnan Li5af92f92023-07-14 14:36:22 +080010265/**
10266 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
10267 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
10268 */
10269TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
10270 // Down on second window
10271 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10272 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10273 {150, 50}))
10274 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10275
10276 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
10277 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
10278
10279 // Down on first window
10280 const MotionEvent secondFingerDownEvent =
10281 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10282 .displayId(ADISPLAY_ID_DEFAULT)
10283 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10284 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10285 .build();
10286 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10287 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10288 InputEventInjectionSync::WAIT_FOR_RESULT))
10289 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10290 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10291 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
10292 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
10293
10294 // Start drag on first window
10295 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
10296
10297 // Trigger cancel
10298 mDispatcher->cancelCurrentTouch();
10299 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
10300 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
10301 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
10302
10303 ASSERT_TRUE(mDispatcher->waitForIdle());
10304 // The D&D finished with nullptr
10305 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
10306
10307 // Remove drag window
10308 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
10309
10310 // Inject a simple gesture, ensure dispatcher not crashed
10311 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10312 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10313 PointF{50, 50}))
10314 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10315 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10316
10317 const MotionEvent moveEvent =
10318 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10319 .displayId(ADISPLAY_ID_DEFAULT)
10320 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10321 .build();
10322 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10323 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
10324 InputEventInjectionSync::WAIT_FOR_RESULT))
10325 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10326 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
10327
10328 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10329 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10330 {50, 50}))
10331 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10332 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
10333}
10334
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000010335TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
10336 // Start hovering over the window.
10337 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10338 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
10339 ADISPLAY_ID_DEFAULT, {50, 50}));
10340
10341 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10342 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10343
10344 ASSERT_FALSE(startDrag(/*sendDown=*/false))
10345 << "Drag and drop should not work with a hovering pointer";
10346}
10347
Vishnu Nair062a8672021-09-03 16:07:44 -070010348class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
10349
10350TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
10351 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010352 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10353 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010354 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010355 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10356 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010357 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010358 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010359 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010360
10361 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010362 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010363 window->assertNoEvents();
10364
Prabir Pradhan678438e2023-04-13 19:32:51 +000010365 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10366 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010367 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10368 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080010369 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070010370 window->assertNoEvents();
10371
10372 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010373 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010374 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010375
Prabir Pradhan678438e2023-04-13 19:32:51 +000010376 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010377 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10378
Prabir Pradhan678438e2023-04-13 19:32:51 +000010379 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10380 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010381 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10382 window->assertNoEvents();
10383}
10384
10385TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
10386 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10387 std::make_shared<FakeApplicationHandle>();
10388 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010389 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10390 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010391 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010392 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010393 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010394 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010395 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10396 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010397 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010398 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010399 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10400 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010401 mDispatcher->onWindowInfosChanged(
10402 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010403 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010404 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010405
10406 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010407 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010408 window->assertNoEvents();
10409
Prabir Pradhan678438e2023-04-13 19:32:51 +000010410 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10411 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010412 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10413 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010414 window->assertNoEvents();
10415
10416 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010417 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010418 mDispatcher->onWindowInfosChanged(
10419 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010420
Prabir Pradhan678438e2023-04-13 19:32:51 +000010421 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010422 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10423
Prabir Pradhan678438e2023-04-13 19:32:51 +000010424 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10425 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010426 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
10427 window->assertNoEvents();
10428}
10429
10430TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
10431 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10432 std::make_shared<FakeApplicationHandle>();
10433 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010434 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10435 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010436 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010437 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010438 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010439 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010440 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10441 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010442 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010443 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010444 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10445 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010446 mDispatcher->onWindowInfosChanged(
10447 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010448 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010449 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010450
10451 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010452 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010453 window->assertNoEvents();
10454
Prabir Pradhan678438e2023-04-13 19:32:51 +000010455 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10456 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010457 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10458 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010459 window->assertNoEvents();
10460
10461 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010462 mDispatcher->onWindowInfosChanged(
10463 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010464
Prabir Pradhan678438e2023-04-13 19:32:51 +000010465 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010466 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10467
Prabir Pradhan678438e2023-04-13 19:32:51 +000010468 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10469 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010470 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10471 window->assertNoEvents();
10472}
10473
Antonio Kantekf16f2832021-09-28 04:39:20 +000010474class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
10475protected:
10476 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000010477 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010478 sp<FakeWindowHandle> mWindow;
10479 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000010480 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010481
10482 void SetUp() override {
10483 InputDispatcherTest::SetUp();
10484
10485 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000010486 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010487 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010488 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010489 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010490 mSecondWindow =
10491 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010492 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000010493 mThirdWindow =
10494 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
10495 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
10496 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010497
10498 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010499 mDispatcher->onWindowInfosChanged(
10500 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
10501 {},
10502 0,
10503 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000010504 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010505 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010506
Antonio Kantek15beb512022-06-13 22:35:41 +000010507 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010508 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010509 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070010510 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
10511 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010512 mThirdWindow->assertNoEvents();
10513 }
10514
10515 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
10516 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010517 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000010518 SECOND_DISPLAY_ID)) {
10519 mWindow->assertNoEvents();
10520 mSecondWindow->assertNoEvents();
10521 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070010522 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000010523 }
10524
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010525 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000010526 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070010527 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
10528 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010529 mWindow->consumeTouchModeEvent(inTouchMode);
10530 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010531 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000010532 }
10533};
10534
Antonio Kantek26defcf2022-02-08 01:12:27 +000010535TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010536 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000010537 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
10538 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010539 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010540}
10541
Antonio Kantek26defcf2022-02-08 01:12:27 +000010542TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
10543 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010544 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010545 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010546 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010547 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010548 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -070010549 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000010550 mWindow->assertNoEvents();
10551 mSecondWindow->assertNoEvents();
10552}
10553
10554TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
10555 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010556 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010557 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010558 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000010559 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010560 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010561}
10562
Antonio Kantekf16f2832021-09-28 04:39:20 +000010563TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010564 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000010565 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
10566 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010567 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010568 mWindow->assertNoEvents();
10569 mSecondWindow->assertNoEvents();
10570}
10571
Antonio Kantek15beb512022-06-13 22:35:41 +000010572TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
10573 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
10574 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10575 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010576 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000010577 mWindow->assertNoEvents();
10578 mSecondWindow->assertNoEvents();
10579 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
10580}
10581
Antonio Kantek48710e42022-03-24 14:19:30 -070010582TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
10583 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010584 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10585 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070010586 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10587 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
10588
10589 // Then remove focus.
10590 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010591 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070010592
10593 // Assert that caller can switch touch mode by owning one of the last interacted window.
10594 const WindowInfo& windowInfo = *mWindow->getInfo();
10595 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10596 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010597 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070010598}
10599
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010600class InputDispatcherSpyWindowTest : public InputDispatcherTest {
10601public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010602 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010603 std::shared_ptr<FakeApplicationHandle> application =
10604 std::make_shared<FakeApplicationHandle>();
10605 std::string name = "Fake Spy ";
10606 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010607 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
10608 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010609 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010610 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010611 return spy;
10612 }
10613
10614 sp<FakeWindowHandle> createForeground() {
10615 std::shared_ptr<FakeApplicationHandle> application =
10616 std::make_shared<FakeApplicationHandle>();
10617 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010618 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
10619 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010620 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010621 return window;
10622 }
10623
10624private:
10625 int mSpyCount{0};
10626};
10627
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010628using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010629/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010630 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
10631 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010632TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070010633 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010634 ScopedSilentDeath _silentDeath;
10635
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010636 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010637 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010638 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010639 ".* not a trusted overlay");
10640}
10641
10642/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010643 * Input injection into a display with a spy window but no foreground windows should succeed.
10644 */
10645TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010646 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010647 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010648
10649 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010650 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010651 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10652 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10653}
10654
10655/**
10656 * Verify the order in which different input windows receive events. The touched foreground window
10657 * (if there is one) should always receive the event first. When there are multiple spy windows, the
10658 * spy windows will receive the event according to their Z-order, where the top-most spy window will
10659 * receive events before ones belows it.
10660 *
10661 * Here, we set up a scenario with four windows in the following Z order from the top:
10662 * spy1, spy2, window, spy3.
10663 * We then inject an event and verify that the foreground "window" receives it first, followed by
10664 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
10665 * window.
10666 */
10667TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
10668 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010669 auto spy1 = createSpy();
10670 auto spy2 = createSpy();
10671 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010672 mDispatcher->onWindowInfosChanged(
10673 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010674 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
10675 const size_t numChannels = channels.size();
10676
Michael Wright8e9a8562022-02-09 13:44:29 +000010677 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010678 if (!epollFd.ok()) {
10679 FAIL() << "Failed to create epoll fd";
10680 }
10681
10682 for (size_t i = 0; i < numChannels; i++) {
10683 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
10684 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
10685 FAIL() << "Failed to add fd to epoll";
10686 }
10687 }
10688
10689 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010690 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010691 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10692
10693 std::vector<size_t> eventOrder;
10694 std::vector<struct epoll_event> events(numChannels);
10695 for (;;) {
10696 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
10697 (100ms).count());
10698 if (nFds < 0) {
10699 FAIL() << "Failed to call epoll_wait";
10700 }
10701 if (nFds == 0) {
10702 break; // epoll_wait timed out
10703 }
10704 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070010705 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070010706 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010707 channels[i]->consumeMotionDown();
10708 }
10709 }
10710
10711 // Verify the order in which the events were received.
10712 EXPECT_EQ(3u, eventOrder.size());
10713 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
10714 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
10715 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
10716}
10717
10718/**
10719 * A spy window using the NOT_TOUCHABLE flag does not receive events.
10720 */
10721TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
10722 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010723 auto spy = createSpy();
10724 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010725 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010726
10727 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010728 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010729 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10730 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10731 spy->assertNoEvents();
10732}
10733
10734/**
10735 * A spy window will only receive gestures that originate within its touchable region. Gestures that
10736 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
10737 * to the window.
10738 */
10739TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
10740 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010741 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010742 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010743 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010744
10745 // Inject an event outside the spy window's touchable region.
10746 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010747 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010748 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10749 window->consumeMotionDown();
10750 spy->assertNoEvents();
10751 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010752 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010753 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10754 window->consumeMotionUp();
10755 spy->assertNoEvents();
10756
10757 // Inject an event inside the spy window's touchable region.
10758 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010759 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010760 {5, 10}))
10761 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10762 window->consumeMotionDown();
10763 spy->consumeMotionDown();
10764}
10765
10766/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010767 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010768 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010769 */
10770TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
10771 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010772 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010773 auto spy = createSpy();
10774 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010775 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010776 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010777 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010778
10779 // Inject an event outside the spy window's frame and touchable region.
10780 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010781 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010782 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010783 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10784 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010785 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010786}
10787
10788/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010789 * Even when a spy window spans over multiple foreground windows, the spy should receive all
10790 * pointers that are down within its bounds.
10791 */
10792TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
10793 auto windowLeft = createForeground();
10794 windowLeft->setFrame({0, 0, 100, 200});
10795 auto windowRight = createForeground();
10796 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010797 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010798 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010799 mDispatcher->onWindowInfosChanged(
10800 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010801
10802 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010803 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010804 {50, 50}))
10805 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10806 windowLeft->consumeMotionDown();
10807 spy->consumeMotionDown();
10808
10809 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010810 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010811 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010812 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10813 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010814 .build();
10815 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010816 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010817 InputEventInjectionSync::WAIT_FOR_RESULT))
10818 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10819 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000010820 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010821}
10822
10823/**
10824 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
10825 * the spy should receive the second pointer with ACTION_DOWN.
10826 */
10827TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
10828 auto window = createForeground();
10829 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010830 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010831 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010832 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010833
10834 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010835 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010836 {50, 50}))
10837 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10838 window->consumeMotionDown();
10839 spyRight->assertNoEvents();
10840
10841 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010842 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010843 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010844 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10845 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010846 .build();
10847 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010848 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010849 InputEventInjectionSync::WAIT_FOR_RESULT))
10850 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010851 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010852 spyRight->consumeMotionDown();
10853}
10854
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010855/**
10856 * The spy window should not be able to affect whether or not touches are split. Only the foreground
10857 * windows should be allowed to control split touch.
10858 */
10859TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010860 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010861 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010862 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010863 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010864
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010865 auto window = createForeground();
10866 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010867
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010868 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010869
10870 // First finger down, no window touched.
10871 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010872 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010873 {100, 200}))
10874 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10875 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10876 window->assertNoEvents();
10877
10878 // Second finger down on window, the window should receive touch down.
10879 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010880 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010881 .displayId(ADISPLAY_ID_DEFAULT)
10882 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010883 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10884 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010885 .build();
10886 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010887 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010888 InputEventInjectionSync::WAIT_FOR_RESULT))
10889 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10890
10891 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000010892 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010893}
10894
10895/**
10896 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
10897 * do not receive key events.
10898 */
10899TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010900 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010901 spy->setFocusable(false);
10902
10903 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010904 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010905 setFocusedWindow(window);
10906 window->consumeFocusEvent(true);
10907
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010908 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010909 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10910 window->consumeKeyDown(ADISPLAY_ID_NONE);
10911
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010912 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010913 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10914 window->consumeKeyUp(ADISPLAY_ID_NONE);
10915
10916 spy->assertNoEvents();
10917}
10918
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010919using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
10920
10921/**
10922 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
10923 * are currently sent to any other windows - including other spy windows - will also be cancelled.
10924 */
10925TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
10926 auto window = createForeground();
10927 auto spy1 = createSpy();
10928 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010929 mDispatcher->onWindowInfosChanged(
10930 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010931
10932 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010933 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010934 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10935 window->consumeMotionDown();
10936 spy1->consumeMotionDown();
10937 spy2->consumeMotionDown();
10938
10939 // Pilfer pointers from the second spy window.
10940 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
10941 spy2->assertNoEvents();
10942 spy1->consumeMotionCancel();
10943 window->consumeMotionCancel();
10944
10945 // The rest of the gesture should only be sent to the second spy window.
10946 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010947 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010948 ADISPLAY_ID_DEFAULT))
10949 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10950 spy2->consumeMotionMove();
10951 spy1->assertNoEvents();
10952 window->assertNoEvents();
10953}
10954
10955/**
10956 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
10957 * in the middle of the gesture.
10958 */
10959TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
10960 auto window = createForeground();
10961 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010962 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010963
10964 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010965 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010966 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10967 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10968 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10969
10970 window->releaseChannel();
10971
10972 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10973
10974 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010975 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010976 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10977 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10978}
10979
10980/**
10981 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
10982 * the spy, but not to any other windows.
10983 */
10984TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
10985 auto spy = createSpy();
10986 auto window = createForeground();
10987
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010988 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010989
10990 // First finger down on the window and the spy.
10991 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010992 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010993 {100, 200}))
10994 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10995 spy->consumeMotionDown();
10996 window->consumeMotionDown();
10997
10998 // Spy window pilfers the pointers.
10999 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11000 window->consumeMotionCancel();
11001
11002 // Second finger down on the window and spy, but the window should not receive the pointer down.
11003 const MotionEvent secondFingerDownEvent =
11004 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11005 .displayId(ADISPLAY_ID_DEFAULT)
11006 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011007 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11008 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011009 .build();
11010 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011011 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011012 InputEventInjectionSync::WAIT_FOR_RESULT))
11013 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11014
Harry Cutts33476232023-01-30 19:57:29 +000011015 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011016
11017 // Third finger goes down outside all windows, so injection should fail.
11018 const MotionEvent thirdFingerDownEvent =
11019 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11020 .displayId(ADISPLAY_ID_DEFAULT)
11021 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011022 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11023 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
11024 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011025 .build();
11026 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011027 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011028 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080011029 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011030
11031 spy->assertNoEvents();
11032 window->assertNoEvents();
11033}
11034
11035/**
11036 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
11037 */
11038TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
11039 auto spy = createSpy();
11040 spy->setFrame(Rect(0, 0, 100, 100));
11041 auto window = createForeground();
11042 window->setFrame(Rect(0, 0, 200, 200));
11043
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011044 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011045
11046 // First finger down on the window only
11047 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011048 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011049 {150, 150}))
11050 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11051 window->consumeMotionDown();
11052
11053 // Second finger down on the spy and window
11054 const MotionEvent secondFingerDownEvent =
11055 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11056 .displayId(ADISPLAY_ID_DEFAULT)
11057 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011058 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11059 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011060 .build();
11061 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011062 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011063 InputEventInjectionSync::WAIT_FOR_RESULT))
11064 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11065 spy->consumeMotionDown();
11066 window->consumeMotionPointerDown(1);
11067
11068 // Third finger down on the spy and window
11069 const MotionEvent thirdFingerDownEvent =
11070 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11071 .displayId(ADISPLAY_ID_DEFAULT)
11072 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011073 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11074 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
11075 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011076 .build();
11077 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011078 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011079 InputEventInjectionSync::WAIT_FOR_RESULT))
11080 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11081 spy->consumeMotionPointerDown(1);
11082 window->consumeMotionPointerDown(2);
11083
11084 // Spy window pilfers the pointers.
11085 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000011086 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
11087 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011088
11089 spy->assertNoEvents();
11090 window->assertNoEvents();
11091}
11092
11093/**
11094 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
11095 * other windows should be canceled. If this results in the cancellation of all pointers for some
11096 * window, then that window should receive ACTION_CANCEL.
11097 */
11098TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
11099 auto spy = createSpy();
11100 spy->setFrame(Rect(0, 0, 100, 100));
11101 auto window = createForeground();
11102 window->setFrame(Rect(0, 0, 200, 200));
11103
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011104 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011105
11106 // First finger down on both spy and window
11107 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011108 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011109 {10, 10}))
11110 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11111 window->consumeMotionDown();
11112 spy->consumeMotionDown();
11113
11114 // Second finger down on the spy and window
11115 const MotionEvent secondFingerDownEvent =
11116 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11117 .displayId(ADISPLAY_ID_DEFAULT)
11118 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011119 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11120 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011121 .build();
11122 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011123 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011124 InputEventInjectionSync::WAIT_FOR_RESULT))
11125 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11126 spy->consumeMotionPointerDown(1);
11127 window->consumeMotionPointerDown(1);
11128
11129 // Spy window pilfers the pointers.
11130 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11131 window->consumeMotionCancel();
11132
11133 spy->assertNoEvents();
11134 window->assertNoEvents();
11135}
11136
11137/**
11138 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
11139 * be sent to other windows
11140 */
11141TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
11142 auto spy = createSpy();
11143 spy->setFrame(Rect(0, 0, 100, 100));
11144 auto window = createForeground();
11145 window->setFrame(Rect(0, 0, 200, 200));
11146
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011147 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011148
11149 // First finger down on both window and spy
11150 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011151 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011152 {10, 10}))
11153 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11154 window->consumeMotionDown();
11155 spy->consumeMotionDown();
11156
11157 // Spy window pilfers the pointers.
11158 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11159 window->consumeMotionCancel();
11160
11161 // Second finger down on the window only
11162 const MotionEvent secondFingerDownEvent =
11163 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11164 .displayId(ADISPLAY_ID_DEFAULT)
11165 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011166 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11167 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011168 .build();
11169 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011170 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011171 InputEventInjectionSync::WAIT_FOR_RESULT))
11172 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11173 window->consumeMotionDown();
11174 window->assertNoEvents();
11175
11176 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
11177 spy->consumeMotionMove();
11178 spy->assertNoEvents();
11179}
11180
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011181/**
11182 * A window on the left and a window on the right. Also, a spy window that's above all of the
11183 * windows, and spanning both left and right windows.
11184 * Send simultaneous motion streams from two different devices, one to the left window, and another
11185 * to the right window.
11186 * Pilfer from spy window.
11187 * Check that the pilfering only affects the pointers that are actually being received by the spy.
11188 */
11189TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
11190 sp<FakeWindowHandle> spy = createSpy();
11191 spy->setFrame(Rect(0, 0, 200, 200));
11192 sp<FakeWindowHandle> leftWindow = createForeground();
11193 leftWindow->setFrame(Rect(0, 0, 100, 100));
11194
11195 sp<FakeWindowHandle> rightWindow = createForeground();
11196 rightWindow->setFrame(Rect(100, 0, 200, 100));
11197
11198 constexpr int32_t stylusDeviceId = 1;
11199 constexpr int32_t touchDeviceId = 2;
11200
11201 mDispatcher->onWindowInfosChanged(
11202 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
11203
11204 // Stylus down on left window and spy
11205 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
11206 .deviceId(stylusDeviceId)
11207 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
11208 .build());
11209 leftWindow->consumeMotionEvent(
11210 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11211 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11212
11213 // Finger down on right window and spy - but spy already has stylus
11214 mDispatcher->notifyMotion(
11215 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11216 .deviceId(touchDeviceId)
11217 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
11218 .build());
11219 rightWindow->consumeMotionEvent(
11220 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011221 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011222
11223 // Act: pilfer from spy. Spy is currently receiving touch events.
11224 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011225 leftWindow->consumeMotionEvent(
11226 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011227 rightWindow->consumeMotionEvent(
11228 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
11229
11230 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
11231 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
11232 .deviceId(stylusDeviceId)
11233 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
11234 .build());
11235 mDispatcher->notifyMotion(
11236 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
11237 .deviceId(touchDeviceId)
11238 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
11239 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011240 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011241
11242 spy->assertNoEvents();
11243 leftWindow->assertNoEvents();
11244 rightWindow->assertNoEvents();
11245}
11246
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000011247TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
11248 auto window = createForeground();
11249 auto spy = createSpy();
11250 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
11251
11252 mDispatcher->notifyMotion(
11253 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11254 .deviceId(1)
11255 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
11256 .build());
11257 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11258 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11259
11260 // Pilfer pointers from the spy window should fail.
11261 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
11262 spy->assertNoEvents();
11263 window->assertNoEvents();
11264}
11265
Prabir Pradhand65552b2021-10-07 11:23:50 -070011266class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
11267public:
11268 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
11269 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11270 std::make_shared<FakeApplicationHandle>();
11271 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011272 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11273 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011274 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011275 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011276 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011277 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011278 overlay->setTrustedOverlay(true);
11279
11280 std::shared_ptr<FakeApplicationHandle> application =
11281 std::make_shared<FakeApplicationHandle>();
11282 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011283 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
11284 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011285 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011286 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011287
11288 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011289 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011290 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011291 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011292 return {std::move(overlay), std::move(window)};
11293 }
11294
11295 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011296 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070011297 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000011298 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070011299 }
11300
11301 void sendStylusEvent(int32_t action) {
11302 NotifyMotionArgs motionArgs =
11303 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
11304 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011305 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000011306 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011307 }
11308};
11309
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011310using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
11311
11312TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070011313 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011314 ScopedSilentDeath _silentDeath;
11315
Prabir Pradhand65552b2021-10-07 11:23:50 -070011316 auto [overlay, window] = setupStylusOverlayScenario();
11317 overlay->setTrustedOverlay(false);
11318 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011319 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
11320 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070011321 ".* not a trusted overlay");
11322}
11323
11324TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
11325 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011326 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011327
11328 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11329 overlay->consumeMotionDown();
11330 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11331 overlay->consumeMotionUp();
11332
11333 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11334 window->consumeMotionDown();
11335 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11336 window->consumeMotionUp();
11337
11338 overlay->assertNoEvents();
11339 window->assertNoEvents();
11340}
11341
11342TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
11343 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011344 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011345 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011346
11347 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11348 overlay->consumeMotionDown();
11349 window->consumeMotionDown();
11350 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11351 overlay->consumeMotionUp();
11352 window->consumeMotionUp();
11353
11354 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11355 window->consumeMotionDown();
11356 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11357 window->consumeMotionUp();
11358
11359 overlay->assertNoEvents();
11360 window->assertNoEvents();
11361}
11362
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011363/**
11364 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
11365 * The scenario is as follows:
11366 * - The stylus interceptor overlay is configured as a spy window.
11367 * - The stylus interceptor spy receives the start of a new stylus gesture.
11368 * - It pilfers pointers and then configures itself to no longer be a spy.
11369 * - The stylus interceptor continues to receive the rest of the gesture.
11370 */
11371TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
11372 auto [overlay, window] = setupStylusOverlayScenario();
11373 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011374 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011375
11376 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11377 overlay->consumeMotionDown();
11378 window->consumeMotionDown();
11379
11380 // The interceptor pilfers the pointers.
11381 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
11382 window->consumeMotionCancel();
11383
11384 // The interceptor configures itself so that it is no longer a spy.
11385 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011386 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011387
11388 // It continues to receive the rest of the stylus gesture.
11389 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
11390 overlay->consumeMotionMove();
11391 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11392 overlay->consumeMotionUp();
11393
11394 window->assertNoEvents();
11395}
11396
Prabir Pradhan5735a322022-04-11 17:23:34 +000011397struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011398 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011399 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000011400 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
11401 std::unique_ptr<InputDispatcher>& mDispatcher;
11402
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011403 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000011404 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
11405
11406 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011407 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011408 ADISPLAY_ID_DEFAULT, {100, 200},
11409 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
11410 AMOTION_EVENT_INVALID_CURSOR_POSITION},
11411 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
11412 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
11413 }
11414
11415 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011416 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011417 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000011418 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000011419 mPolicyFlags);
11420 }
11421
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011422 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000011423 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11424 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011425 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11426 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000011427 window->setOwnerInfo(mPid, mUid);
11428 return window;
11429 }
11430};
11431
11432using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
11433
11434TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011435 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011436 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011437 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011438
11439 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11440 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11441 window->consumeMotionDown();
11442
11443 setFocusedWindow(window);
11444 window->consumeFocusEvent(true);
11445
11446 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11447 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11448 window->consumeKeyDown(ADISPLAY_ID_NONE);
11449}
11450
11451TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011452 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011453 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011454 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011455
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011456 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011457 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11458 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11459
11460 setFocusedWindow(window);
11461 window->consumeFocusEvent(true);
11462
11463 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11464 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11465 window->assertNoEvents();
11466}
11467
11468TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011469 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011470 auto window = owner.createWindow("Owned window");
11471 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011472 spy->setSpy(true);
11473 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011474 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011475
11476 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11477 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11478 spy->consumeMotionDown();
11479 window->consumeMotionDown();
11480}
11481
11482TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011483 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011484 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011485
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011486 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011487 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011488 randosSpy->setSpy(true);
11489 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011490 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011491
11492 // The event is targeted at owner's window, so injection should succeed, but the spy should
11493 // not receive the event.
11494 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11495 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11496 randosSpy->assertNoEvents();
11497 window->consumeMotionDown();
11498}
11499
11500TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011501 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011502 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011503
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011504 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011505 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011506 randosSpy->setSpy(true);
11507 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011508 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011509
11510 // A user that has injection permission can inject into any window.
11511 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011512 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011513 ADISPLAY_ID_DEFAULT));
11514 randosSpy->consumeMotionDown();
11515 window->consumeMotionDown();
11516
11517 setFocusedWindow(randosSpy);
11518 randosSpy->consumeFocusEvent(true);
11519
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011520 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000011521 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
11522 window->assertNoEvents();
11523}
11524
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011525TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011526 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011527 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011528
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011529 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011530 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011531 randosWindow->setFrame(Rect{-10, -10, -5, -5});
11532 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011533 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011534
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011535 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000011536 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11537 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11538 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011539 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000011540}
11541
Prabir Pradhan64f21d22023-11-28 21:19:42 +000011542using InputDispatcherPointerInWindowTest = InputDispatcherTest;
11543
11544TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
11545 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11546
11547 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11548 ADISPLAY_ID_DEFAULT);
11549 left->setFrame(Rect(0, 0, 100, 100));
11550 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11551 "Right Window", ADISPLAY_ID_DEFAULT);
11552 right->setFrame(Rect(100, 0, 200, 100));
11553 sp<FakeWindowHandle> spy =
11554 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
11555 spy->setFrame(Rect(0, 0, 200, 100));
11556 spy->setTrustedOverlay(true);
11557 spy->setSpy(true);
11558
11559 mDispatcher->onWindowInfosChanged(
11560 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
11561
11562 // Hover into the left window.
11563 mDispatcher->notifyMotion(
11564 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
11565 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
11566 .build());
11567
11568 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11569 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11570
11571 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11572 /*pointerId=*/0));
11573 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11574 /*pointerId=*/0));
11575 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11576 /*pointerId=*/0));
11577
11578 // Hover move to the right window.
11579 mDispatcher->notifyMotion(
11580 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
11581 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
11582 .build());
11583
11584 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11585 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11586 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
11587
11588 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11589 /*pointerId=*/0));
11590 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11591 /*pointerId=*/0));
11592 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11593 /*pointerId=*/0));
11594
11595 // Stop hovering.
11596 mDispatcher->notifyMotion(
11597 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
11598 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
11599 .build());
11600
11601 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11602 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11603
11604 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11605 /*pointerId=*/0));
11606 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11607 /*pointerId=*/0));
11608 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11609 /*pointerId=*/0));
11610}
11611
11612TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
11613 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11614
11615 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11616 ADISPLAY_ID_DEFAULT);
11617 left->setFrame(Rect(0, 0, 100, 100));
11618 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11619 "Right Window", ADISPLAY_ID_DEFAULT);
11620 right->setFrame(Rect(100, 0, 200, 100));
11621 sp<FakeWindowHandle> spy =
11622 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
11623 spy->setFrame(Rect(0, 0, 200, 100));
11624 spy->setTrustedOverlay(true);
11625 spy->setSpy(true);
11626
11627 mDispatcher->onWindowInfosChanged(
11628 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
11629
11630 // First pointer down on left window.
11631 mDispatcher->notifyMotion(
11632 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11633 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11634 .build());
11635
11636 left->consumeMotionDown();
11637 spy->consumeMotionDown();
11638
11639 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11640 /*pointerId=*/0));
11641 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11642 /*pointerId=*/0));
11643 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11644 /*pointerId=*/0));
11645
11646 // Second pointer down on right window.
11647 mDispatcher->notifyMotion(
11648 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11649 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11650 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
11651 .build());
11652
11653 left->consumeMotionMove();
11654 right->consumeMotionDown();
11655 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
11656
11657 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11658 /*pointerId=*/0));
11659 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11660 /*pointerId=*/0));
11661 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11662 /*pointerId=*/0));
11663 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11664 /*pointerId=*/1));
11665 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11666 /*pointerId=*/1));
11667 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11668 /*pointerId=*/1));
11669
11670 // Second pointer up.
11671 mDispatcher->notifyMotion(
11672 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
11673 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11674 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
11675 .build());
11676
11677 left->consumeMotionMove();
11678 right->consumeMotionUp();
11679 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
11680
11681 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11682 /*pointerId=*/0));
11683 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11684 /*pointerId=*/0));
11685 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11686 /*pointerId=*/0));
11687 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11688 /*pointerId=*/1));
11689 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11690 /*pointerId=*/1));
11691 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11692 /*pointerId=*/1));
11693
11694 // First pointer up.
11695 mDispatcher->notifyMotion(
11696 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
11697 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11698 .build());
11699
11700 left->consumeMotionUp();
11701 spy->consumeMotionUp();
11702
11703 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11704 /*pointerId=*/0));
11705 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11706 /*pointerId=*/0));
11707 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11708 /*pointerId=*/0));
11709}
11710
11711TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
11712 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11713
11714 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11715 ADISPLAY_ID_DEFAULT);
11716 left->setFrame(Rect(0, 0, 100, 100));
11717 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11718 "Right Window", ADISPLAY_ID_DEFAULT);
11719 right->setFrame(Rect(100, 0, 200, 100));
11720
11721 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
11722
11723 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11724 /*pointerId=*/0));
11725 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11726 /*pointerId=*/0));
11727
11728 // Hover move into the window.
11729 mDispatcher->notifyMotion(
11730 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11731 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
11732 .rawXCursorPosition(50)
11733 .rawYCursorPosition(50)
11734 .deviceId(DEVICE_ID)
11735 .build());
11736
11737 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11738
11739 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11740 /*pointerId=*/0));
11741
11742 // Move the mouse with another device. This cancels the hovering pointer from the first device.
11743 mDispatcher->notifyMotion(
11744 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11745 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
11746 .rawXCursorPosition(51)
11747 .rawYCursorPosition(50)
11748 .deviceId(SECOND_DEVICE_ID)
11749 .build());
11750
11751 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11752 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11753
11754 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
11755 // a HOVER_EXIT from the first device.
11756 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11757 /*pointerId=*/0));
11758 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
11759 SECOND_DEVICE_ID,
11760 /*pointerId=*/0));
11761
11762 // Move the mouse outside the window. Document the current behavior, where the window does not
11763 // receive HOVER_EXIT even though the mouse left the window.
11764 mDispatcher->notifyMotion(
11765 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11766 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
11767 .rawXCursorPosition(150)
11768 .rawYCursorPosition(50)
11769 .deviceId(SECOND_DEVICE_ID)
11770 .build());
11771
11772 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11773 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11774 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11775 /*pointerId=*/0));
11776 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
11777 SECOND_DEVICE_ID,
11778 /*pointerId=*/0));
11779}
11780
Garfield Tane84e6f92019-08-29 17:28:41 -070011781} // namespace android::inputdispatcher